100 Little Programming Exercises – go-left Software - https://go-left.com/blog/programming/100-little-programming-exercises/
これのReverse The Inputです。引数は自動的に、スペースで区切られた単語ごとに配列に入れられるので、その配列を逆順にすればいいだけですが、最後の要素"END"は逆順にしません。
とりあえず書いたのは以下のコード。
static void Main(string[] args) { var list = args.ToList(); if (list.Last() != "END") { Console.WriteLine("args.Last() != \"END\""); } else { //http://melma.com/backnumber_120830_4798410/ //IEnumerable<T>.Reverse()は範囲の指定ができない。 //List<T>.Reverse()は範囲指定が出来るが、返り値がvoid。 list.RemoveAt(list.Count() - 1); list.Reverse<string>().ToList().ForEach(arg => Console.WriteLine(arg)); } }
例外処理はしておらず、LINQ拡張メソッドではなくList<T>の関数を呼んでるので、行数が多めだと思われます。
本来は多分配列の逆順を実装する練習なんでしょうけど、各要素を後ろから挿入するくらいしか思いつかなかった…
最初は最後の要素以外のReverse()(List<T>.Reverse(Int32, Int32))しようと思ったんですけど、RemoveしてIEnumerable<T>.Reverse()のほうがいい気がした。
IEnumerableだかにForEachが無いから、ListのForEachを使うためだけにToList()してる(どうやら副作用回避のため実装してないけれど、皆同様の拡張メソッド作ってしまうみたいだね)。
LINQ拡張メソッドのTake()を使う
結局、自分が困っているのは「どうやって最後の要素以外を逆順するか?」ということで、上の例だとRemoveAt()を用いてList<string>から要素を削除して、それからReverse()して対処してるわけです。んでも拡張メソッド一覧見てたら、「配列の一部だけを抜き出す」というTake()を見つけたので、じゃあそっちのほうが一行で済むよね?ということでこうしました。
static void Main(string[] args) { var endKey = "END"; if (args.Last() != endKey) { Console.WriteLine("args.Last() != " + endKey); } else { //http://melma.com/backnumber_120830_4798410/ //IEnumerable<T>.Reverse()は範囲の指定ができない。 //List<T>.Reverse()は範囲指定が出来るが、返り値がvoid。 args.ToList() .Take(args.Length - 1) .Reverse<string>() .ToList().ForEach(arg => Console.WriteLine(arg)); } }このコードの問題は、args.ToList()した後に、argsのListを幾つ抜き出す(Take()する)かの指定に、Listする前のargsの要素数を参考にしているところ…本当だったらList<T>.Countを使うべきなんだろうけど、どうしたものか…
これは病院から帰ってきて思いついたもの。