LinqのReverseメソッドはListを逆順で操作できる

foreach文で逆順にループを回したり、
Listを逆順に操作したくなったことはありませんか?

効率化を求めていたり、順番に意味がある場合は、
しばしば逆からListを操作したくなるものです。

しかし、逆順に処理しているつもりが、実際はListを頭から処理していて・・・

と効率化しているようで実はリソースばかり消費していると悲しいですね。

そこで今回は、しっかりと逆順になるメソッド、

そして、逆順と合わせて使いたいListメソッドの紹介をします。

それでは、本文をご覧ください。

LinqのReverseメソッドはListを後ろから操作できる

まずは結論です。

foreachで逆順にするにはReserseメソッドを使う

  • foreachはListなどの「繰り返し」に対してループをさせることができる

「繰り返し」は先頭から処理するのが基本ですが、Reverseメソッドを使えば後方から処理することができます。


Reverseの中身はi--のループ

Reverseメソッドのコードを見ると、逆から取得していることがわかります。

ちょっと重要なポイントを、ピックアップしてみましょう。


Reverseは「i++」、で回すループではなく、減少していく「i--」で回すループ。

yield returnについてのくわしい説明は割愛しますが、

ここで注目するのは

「int i = buffer.count – 1」で一番後ろからiが始まり、
ループするごとに「i--」で i が一つずつ減っていくことです。

そう、for文で逆からやることをReverseメソッドは代わりにやってくれます。

ReverseメソッドはOrderbyよりも高速

OrderByメソッドとOrderByDescendingメソッドもまた順番に関わる機能です。
うまく使えば、逆順にすることができます。

OrderByとOrderByDescendingで反転して使うことはできる

Orderby・OrderByDescendingはそれぞれ並び替えの機能をもっています。

並び替えの機能を使えば、逆順に要素を並び変えられます。

Orderby・OrderByDescendingで逆順にするには、並び変える作業が発生します。

並び替えていくには一つ一つの要素を比較したりします。

つまり、要素を並び替える過程で、全要素を処理するので、
コスト的にはループが回ってしまっているようなものです。

OrderByとOrderByDescendingはあくまで並び替え

もちろん、柔軟な並び替えはOrderby・OrderByDescendingにしかできません。

単純に後ろから要素を取り出す作業では、Orderby・OrderByDescendingはちょっと機能過多なのです。

効率よく逆順にするならばOrderby・OrderByDescendingよりもReverseメソッドの利用をお勧めします。

注意:LinqじゃないReverseメソッド

System.Collections.GenericのReverseメソッドに要注意しましょう。

もともとListにあるメソッドです。

メソッド名まで一緒ですし、逆順するという機能も一緒です。

では、なぜ注意しないといけないのか?

LinqのReverseメソッドとは異なり、
返値もvoidなのでほかのLinqメソッドに繋ぐことができません。

この後紹介する「Reverseメソッドと相性が良い機能」も必然的に使えなくなります。

対策としては、Linqのメソッドを利用するにはAsQueryableメソッドもしくはAsEnumerableメソッドをはさめばOKです。


Reverseメソッドと合わせて使いたいTakeメソッドとSkipメソッド

Reverseメソッドと相性が良い機能を代表して2つ紹介します。

TakeメソッドとSkipメソッドです。

せっかく反転して処理をするのであれば、ループを最後まで回すことなく操作を終わらせたいですね。
というのも、後ろから処理をするには、効率化したいからです。

しかし、ループを回し切ってしまっては、順番に処理するのも逆順に処理するのも、
コスト的には、大して変わらない結果になってしまいます。

そこで、効率的に逆順を使うためのメソッド、TakeメソッドとSkipメソッドの出番です。

これらを使えば、イメージの通りに後ろから要素を取り出せます。


Takeメソッドは指定した要素数を取り出す機能で、

Skipメソッドは指定した要素数を飛ばす機能です。

必要のない要素を飛ばしたり、途中で要素の取り出しをやめることは、
ループを回しきらないので、Reverseメソッドと相性は良いですね。

逆順に速度をもとめるならfor文

実際foreachやLinqメソッドを利用せずとも、for文で逆順が可能です。

単純に逆順に処理する例としてfor文を見ておきましょう。


Linqと比べるとfor文のほうが速度がでます。

for文を拡張していった先がLinqなので当たり前といえば、当たり前ですが。

しかし、Linqを使うメリットはそもそも、速度だけではありません。

ListをLinqで操作する理由の一つは、コードの伝わりやすさにあります。

状況に応じて使い分けたいですね。

まとめ

それでは今回の記事をまとめます。

  • foreachやLinqで逆順にするにはReserseメソッドを使う
  • Orderby・OrderByDescendinは逆順には向かない
  • Linqで操作するならReverseはTake,Skipと一緒に使おう
  • 速度を求めるならfor文

では。