2013-04-24 9 views
18

私は、オブジェクトのリストで重複をチェックする本当に高速な方法を探しています。オブジェクトのリストの重複をチェックするC#

...

私はオブジェクトがあるとし...私は単にリストをループして手動で比較をそのようにやって考えていたが、私は、LINQは、よりエレガントな解決策を提供するかもしれないと思いました

public class dupeCheckee 
{ 
    public string checkThis { get; set; } 
    public string checkThat { get; set; } 

    dupeCheckee(string val, string val2) 
    { 
     checkThis = val; 
     checkThat = val2; 
    } 
} 

そして私は、私はそのリストにdupesを見つける必要があり、それらのオブジェクトのリスト

List<dupeCheckee> dupList = new List<dupeCheckee>(); 
dupList.Add(new dupeCheckee("test1", "value1")); 
dupList.Add(new dupeCheckee("test2", "value1")); 
dupList.Add(new dupeCheckee("test3", "value1")); 
dupList.Add(new dupeCheckee("test1", "value1"));//dupe 
dupList.Add(new dupeCheckee("test2", "value1"));//dupe... 
dupList.Add(new dupeCheckee("test4", "value1")); 
dupList.Add(new dupeCheckee("test5", "value1")); 
dupList.Add(new dupeCheckee("test1", "value2"));//not dupe 

を持っています。私がそれを見つけると、私はいくつかの追加ロジックを行う必要があります 必ずしもそれらを削除する必要はありません。

私はLINQを使用すると、私のGROUPBYが例外をスローする方法をいくつか...

'System.Collections.Generic.List<dupeCheckee>' does not contain a definition for 'GroupBy' and no extension method 'GroupBy' accepting a first argument of type 'System.Collections.Generic.List<dupeCheckee>' could be found (are you missing a using directive or an assembly reference?) 
私は、ライブラリをしないのですと私に語っている

。私は苦労してどれを考え出しているのですか。

一度私はそれを理解したら、どのように本質的にそれらの2つの条件をチェックするのでしょうか... IE checkThisとcheckThatはどちらも複数回出現しますか?

UPDATE:私はこれは私が迅速な研究を行った後、思い付いたLINQクエリで

思い付いた...

test.Count != test.Select(c => new { c.checkThat, c.checkThis }).Distinct().Count() 

これは間違いなく優れているかどうかは定かでありませんよこの答えよりも...

私は最初の文をif else節に入れることができます。私はまた、迅速なテストを実行しました。重複リストは、私が0を期待していたときに私に戻ってきましたが、私が使用したセットの1つに重複があったという事実を正しく示しました。

List<DupeCheckee> test = new List<DupeCheckee>{ 
    new DupeCheckee("test0", "test1"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test1", "test2"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test2", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test3", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test0", "test5"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test1", "test6"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test2", "test7"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test3", "test8"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test0", "test5"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test1", "test1"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test2", "test2"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test3", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test4", "test4"),//{ checkThis = "test", checkThat = "test1"} 

}; 

んdupes ...

 List<DupeCheckee> test2 = new List<DupeCheckee>{ 
    new DupeCheckee("test0", "test1"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test1", "test2"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test2", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test3", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test4", "test5"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test5", "test6"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test6", "test7"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test7", "test8"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test8", "test5"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test9", "test1"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test2", "test2"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test3", "test3"),//{ checkThis = "test", checkThat = "test1"} 
    new DupeCheckee("test4", "test4"),//{ checkThis = "test", checkThat = "test1"} 

}; 
+1

csファイルの先頭に 'using System.Linq;'を追加すると 'GroupBy'が動作します。 –

+0

ちょうど私がそれを見逃していたことがわかった。ありがとう。 – SoftwareSavant

+2

Ermいいえdupesにはdupe test3、test3がありません –

答えて

30

System.Linqを参照する必要があります(例:using System.Linq

あなたはこのあなたを与えるグループは、すべての重複を

var dupes = dupList.GroupBy(x => new {x.checkThis, x.checkThat}) 
        .Where(x => x.Skip(1).Any()); 

を行うことができ、その後重複のテストは、その後

var hasDupes = dupList.GroupBy(x => new {x.checkThis, x.checkThat}) 
        .Where(x => x.Skip(1).Any()).Any(); 

あるいはToList()またはToArray()を呼ぶだろう結果の計算を強制的に実行すると、重複を確認して調べることができます。例えば

..あなたをグループごとに、各項目は、プロパティ内のプロパティindexアイテムで元のインデックスを保存するグループを与える代わりに

var dupes = dupList.GroupBy(x => new {x.checkThis, x.checkThat}) 
        .Where(x => x.Skip(1).Any()).ToArray(); 
if (dupes.Any()) { 
    foreach (var dupeList in dupes) { 
    Console.WriteLine(string.Format("checkThis={0},checkThat={1} has {2} duplicates", 
         duplist.Key.checkThis, 
         duplist.Key.checkThat, 
         duplist.Count() - 1)); 
    } 

} 

var dupes = dupList.Select((x, i) => new { index = i, value = x}) 
        .GroupBy(x => new {x.value.checkThis, x.value.checkThat}) 
        .Where(x => x.Skip(1).Any()); 

value

+0

私は本当にその商品がまったく二重引用符を持っているかどうかを見ています。それらの中にすべての重複を含むいくつかの 'List 'を持っているのはいいだろう...ユーザーが後でそれらを削除したいならそれはいいだろうが、私は本当にリストに重複があるかどうかを調べたいだけだ。 – SoftwareSavant

+0

@DmainEventこれは何をするのですか?真偽があれば 'dupes.Any()'をチェックし、重複がある場合は –

+0

私の解決策を見て、私の解決策が見つからないかどうか確認してください。私はあなたと私の両方を試してみました。 – SoftwareSavant

0

は、LINQ、例えばでSELECT DISTINCTを実行します。ここでは

Dupes私はこれをテストするために使用するデータセットは....ですHow can I do SELECT UNIQUE with LINQ?

次に、別個の結果のカウントを非明瞭な結果と比較する。これは、リストが2倍の場合、あなたにブーリアン(boolean)を与えます。

また、キーが一意であることを保証する辞書を使用することもできます。

+0

dupesで何かしたいのなら、 'GroupBy'が良い方法です。 –

+0

@ダニエル私はそれをアップヴォートすることができ、ユーザーは答えとしてマークすることができるように答えとして投稿してください! – MatthewMartin

1

これはあなたが探しているものだと思います。

List<dupeChecke> duplicates = dupeList.GroupBy(x => x) 
            .SelectMany(g => g.Skip(1)); 
+1

'dupeCheckee'のequalsチェックで、 'checkThis'と' checkThat'は等しくなります。 –

+0

@BobVale:彼はさらにそれを打破したかった気づいていない!あなたのコメントupvoted。 –

0

メモリオブジェクトの場合、私は常にDistinct LINQメソッドを使用して、ソリューションに比較関数を追加します。

public class dupeCheckee 
{ 
    public string checkThis { get; set; } 
    public string checkThat { get; set; } 

    dupeCheckee(string val, string val2) 
    { 
     checkThis = val; 
     checkThat = val2; 
    } 

    public class Comparer : IEqualityComparer<dupeCheckee> 
    { 
     public bool Equals(dupeCheckee x, dupeCheckee y) 
     { 
      if (x == null || y == null) 
       return false; 

      return x.CheckThis == y.CheckThis && x.CheckThat == y.CheckThat; 
     } 

     public int GetHashCode(dupeCheckee obj) 
     { 
      if (obj == null) 
       return 0; 

      return (obj.CheckThis == null ? 0 : obj.CheckThis.GetHashCode())^
       (obj.CheckThat == null ? 0 : obj.CheckThat.GetHashCode()); 
     } 
    } 
} 

は今はまったく重複がある場合、私は知っているためにこれを使用して好き

List<dupeCheckee> dupList = new List<dupeCheckee>(); 
dupList.Add(new dupeCheckee("test1", "value1")); 
dupList.Add(new dupeCheckee("test2", "value1")); 
dupList.Add(new dupeCheckee("test3", "value1")); 
dupList.Add(new dupeCheckee("test1", "value1"));//dupe 
dupList.Add(new dupeCheckee("test2", "value1"));//dupe... 
dupList.Add(new dupeCheckee("test4", "value1")); 
dupList.Add(new dupeCheckee("test5", "value1")); 
dupList.Add(new dupeCheckee("test1", "value2"));//not dupe 

var distinct = dupList.Distinct(dupeCheckee.Comparer); 
+0

これは別のリストを取得していますが、私のリストにそのリストが含まれていないかどうか調べたいと思っています。 – SoftwareSavant

0

呼び出すことができます。文字列があり、重複する文字があるかどうかを知りたいとします。これは私が使用しているものです。

string text = "this is some text"; 

var hasDupes = text.GroupBy(x => x).Any(grp => grp.Count() > 1); 

重複の数が何であっても知りたい場合は、これを使用します。手紙の3

合計I:の2

総手紙の

var totalDupeItems = text.GroupBy(x => x).Count(grp => grp.Count() > 1); 

だから、たとえば、文字tの

総...これを持っている "これは、いくつかのテキストです" :文字Eの3

全2

ように可変totalDupeItemsが4に等しくなります。 4種類の重複があります。

デュプリケートの内容に関係なく、デュプリケートの総量を取得したい場合は、これを使用します。

var totalDupes = letters.GroupBy(x => x).Where(grp => grp.Count() > 1).Sum(grp => grp.Count()); 

ように可変totalDupesこれは、一緒になって追加された各デュープタイプの総重複アイテムである10あろう。

5

あり、作業のソリューションの膨大な量だったが、私は次の解決策は、上記のすべて、その後、より透明かつ理解しやすいだろうと思います。

var hasDuplicatedEntries = ListWithPossibleDuplicates 
            .GroupBy(YourGroupingExpression) 
            .Any(e => e.Count() > 1); 
if(hasDuplicatedKeys) 
{ 
    // Do what ever you want in case when list contains duplicates 
} 
0

重複が例外をスローが発生した場合。辞書は、キーを単独でチェックします。 これが最も簡単な方法です。

try 
{ 
    dupList.ToDictionary(a=>new {a.checkThis,a.checkThat}); 
} 
catch{ 
//message: list items is not uniqe 
} 
関連する問題