2020年10月04日
川俣晶の縁側ソフトウェアC# コーディング How To total 1675 count

【入門級】配列を逆順で取り出す6つの方法

Written By: 川俣 晶連絡先

配列を逆順でアクセスしたい §

 サンプルソースに6パターン書いてみました。

 方法1は普通にforループをまわして添え字にアクセスする際に最大値から引いて逆順の添え字を作り出します。

 方法2はforループを逆順でまわしてしまいます。

 方法3はLINQのRverseメソッドで逆順にします。ソースは最も簡潔ですが実行効率はforに負けます。

 方法4はSkipする数を減らしていき結果として逆順でアクセスします。これもLINQです。

 方法5はLINQで最後の要素を取得して、1つ1つ列挙の長さを切り詰めていきます。

 方法6は再帰という手法を使った例です。forもforeachも使いませんが、データが大きいとスタックを大量に消費します。効率も良くありません。

 お勧めは方法1か2か3です。

 4と5と6は【そういう方法もある】という程度で理解しておき、特に覚える必要はありません。

罠の数々 §

  • やり方は多いがどれが正解という話ではない。状況、用途によって使い分けられるようにバリエーションの特徴を理解しておこう
  • 関数型の言語を使う場合は方法6の再帰が必要になる場合があるが、C#は関数型ではないので必須ではない。ただし、C#でも再帰を使った方が良いケースはあるので、再帰は理解しておこう

参考リンク §

for (C# リファレンス)

Enumerable.Reverse<TSource>(IEnumerable<TSource>) メソッド

Enumerable.Skip<TSource>(IEnumerable<TSource>, Int32) メソッド

Enumerable.First メソッド

Enumerable.Take<TSource>(IEnumerable<TSource>, Int32) メソッド

Enumerable.Count メソッド

 単純に逆順にするだけならReverseメソッドが最強である。しかし、単純に逆順ではなく加工が必要なら、他のメソッドを組み合わせで実現することになる。SkipメソッドやTakeメソッドの出番だ。上記リンクから、メソッドの機能とバリエーションを確認しておこう。

 それから、効率重視だとLINQは弱い。forループを回した方が速いこともある。forループを自由自在に使えるように上記リンクから飛んで機能を確認しておこう。

リポジトリ §

https://github.com/autumn009/cshowto

Reverse §

using System;

using System.Collections.Generic;

using System.Linq;

class Program

{

    private static void recursion(IEnumerable<int> e)

    {

        if (e.Count() > 0)

        {

            recursion(e.Skip(1));

            Console.Write(e.First());

        }

    }

    static void Main()

    {

        int[] ar = { 1, 2, 3 };

        // 方法1 ストレートfor

        for (int i = 0; i < ar.Length; i++)

        {

            Console.Write(ar[ar.Length-i-1]);

        }

        Console.WriteLine();

        // 方法2 リバースfor

        for (int i = ar.Length - 1; i >= 0; i--)

        {

            Console.Write(ar[i]);

        }

        Console.WriteLine();

        // 方法3 LINQ

        foreach (var item in ar.Reverse())

        {

            Console.Write(item);

        }

        Console.WriteLine();

        // 方法4 LINQ2

        for (int i = 0; i < ar.Length; i++)

        {

            Console.Write(ar.Skip(ar.Length-i-1).First());

        }

        Console.WriteLine();

        // 方法5 LINQ3

        IEnumerable<int> a = ar.ToArray();

        for (; ; ) 

        {

            if (a.Count() == 0) break;

            Console.Write(a.Last());

            a = a.Take(a.Count()-1);

        }

        Console.WriteLine();

        // 方法6 再帰

        recursion(ar);

        Console.WriteLine();

    }

}

実行結果

321

321

321

321

321

321

COOL C# CREW

C#ハウツー連載の解説増量、カラーのソース、新規書き下ろし追加の読みやすい単行本はこちら。

C#ハウツー: 逆引き入門・こんな機能はどう書くの?