トップページに戻る    次のC#のサンプルへ    前のC#のサンプルへ

11-4 Arrayのuniq

問題

Array(複数の値が配列状になっているもの)xsが与えられたときに、
同じ値が2回以上出現しないように、
2回目以降の出現を取り除いたArrayを返すコードを書いてください。
Rubyで表現すると下のようになります。

irb(main):001:0> xs = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]
=> [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]
irb(main):002:0> xs.uniq
=> [3, 1, 4, 5, 9, 2, 6, 8, 7]

間違えないように:よくある「ハッシュを使う」「集合オブジェクトを使う」などの方法は
順番が乱れてしまうので使えません。
出現順序を守りつつ、2回目以降の出現だけを取り除いてください。


ソース(LINQで連番付与)

using System;
using System.Linq;

class Program
{
    static void Main()
    {
        int[] intArr = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9 };
        int cnt = 0;
        var query = intArr.Select(X => new { rn = ++cnt, Val = X })
                          .GroupBy(X => X.Val)
                          .Select(X => new { X.Key, minRn = X.Min(Y => Y.rn) })
                          .OrderBy(X => X.minRn);

        foreach (var each in query) {
            Console.WriteLine(each);
        }
    }
}


ソース(LINQとListジェネリックを使用)

using System;
using System.Linq;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        int[] intArr = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9 };
        var AppearList = new List<int>();
        var query = intArr.Where(X =>
        {
            if (AppearList.Contains(X)) return false;
            else {
                AppearList.Add(X);
                return true;
            }
        });

        foreach (var each in query) {
            Console.WriteLine(each);
        }
    }
}


実行結果

{ Key = 3, minRn = 1 }
{ Key = 1, minRn = 2 }
{ Key = 4, minRn = 3 }
{ Key = 5, minRn = 5 }
{ Key = 9, minRn = 6 }
{ Key = 2, minRn = 7 }
{ Key = 6, minRn = 8 }
{ Key = 8, minRn = 12 }
{ Key = 7, minRn = 14 }


解説

LINQのみで加工するより、Where拡張メソッドでListジェネリックを使用するのが
分かりやすそうですね。