2014年07月13日

C#で配列のuniq

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その24


■問題 (出題者:にしお さん)
アレイ(複数の値が配列状になっているもの)xsが与えられたときに、同じ値が2回以上出現しないように、2回目以降の出現を取り除いたアレイを返すコードを書いてください。 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 to Objects の Distinctメソッド使えばOKだと思います。出現順は保持されていたと記憶しています。
 
でも、ここでは、Distinctメソッドを使わないコードとしました。結果用リストに順に値を入れていくのですが、その際、すでに結果用リストにあるものは 入れないようにするという、ごくありふれたコードです。 いちおう、要素の型に依存しないようジェネリックス使ってます。

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

namespace Doukaku.Org {
    class Program {
        static void Main(string[] args) {
            int[] nums = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9 };
            var result = Uniq(nums);
            string s = String.Join(", ", result.Select(n => n.ToString()).ToArray());
            Console.WriteLine("[{0}]", s);

            Console.ReadLine();
        }

        static T[] Uniq<T>(T[] array) {
            List<T> list = new List<T>();
            foreach (var x in array) {
                if (!list.Contains(x))
                    list.Add(x);
            }
            return list.ToArray();
        }
    }
}


 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/52377030