2011-11-08 13 views
2

私は、(Funcとして与えられた)いくつかの述語に対して真である要素がコレクション内に正確にあるかどうかをチェックする方法があります。LINQ c#コレクション内の一意の要素

public bool ExistsUnique(Func<T, bool> p) 
    { 
     var tempCol = from i in MyCollection where p(i) select i; 
     return (tempCol.Count() == 1); 
    } 

これに伴う問題も述語 にも当てはまる第二の要素が発見された場合、カウントはどちらかそれを意味し、どのまだ1である(例えば、同じ文字列の2がコレクション内に存在する)ということですすでに存在しているため、最初の要素をオーバーライドしたり、2番目の要素を追加したりしません。

どのように私はこの方法を修正することができますか? thx /Peter

+0

私はこの疑問を疑っています(http://stackoverflow.com/questions/2740109/can-someone-please-explain-this-lazy-evaluation-code)とその答えがあなたを助けるかもしれません。 – ssamuel

答えて

1

その他の問題があります。私はあなたの述語を疑うでしょう。たとえば、これは予想通り、2の数を返します:

 List<string> MyCollection = new List<string>() 
     { 
      "hello", 
      "hello" 
     }; 
     var tempCol = from i in MyCollection where i == "hello" select i; 
     int count = tempCol.Count(); 

私はそれはあなたがどちらか、それを呼んでいる方法だということを疑います。以下の作品(falseを返す):

static List<string> MyCollection = new List<string>() 
     { 
      "hello", 
      "hello" 
     }; 

    static bool ExistsUnique(Func<string, bool> p) 
    { 
     var tempCol = from i in MyCollection where p(i) select i; 
     return tempCol.Count() == 1; 
    } 

    static void DoIt() 
    { 
     bool isUnique = ExistsUnique((s) => s.Equals("hello")); 
     Console.WriteLine(isUnique); 
    } 
+0

私はあなたが正しいかもしれないと思います。述語my_set.ExistsUnique(s => s.Equals( "Hello"))でも問題ありません。私はExistsメソッドで全く同じものを使用しています(少なくとも1つの要素が真であるかどうかを確認するだけです)。それは私がp(i)と書く方法かもしれませんか? – PNS

+0

@PNS:更新された回答をご覧ください。私は問題があなたがそれを呼んでいる方法であるとは思わない。 –

+0

今私は本当に混乱しています。あなたのメソッドとの唯一の違いは自分のExistsUniqueメソッドが文字列、boolを取るのに対し、私はT、boolを取りますが、まだ動作するはずです。右? – PNS

1

tempColは完全にMyCollectionまでループしていますか? はCount()です。完全なループを強制するメソッドか、それとも遅延していますか?

例えばtempCol.ToList().Countは正しい結果を返しますか?

+0

私はp(i)と言ってみました。 !p(i)コレクション内のすべての要素を一度(重複なし)追加したところ、実際にすべての要素を繰り返し処理したかどうかを確認するだけです。 – PNS

2

あなたはこのようにLINQが提供するSingle()方法を使用することができます

public bool ExistsUnique(Func<T, bool> p) 
{ 
    try 
    { 
     var temp = myCollection.Single(x => p(x)); 
    } 
    catch(Exception e) 
    { 
     // log exception 
     return false; 
    } 

    return true; 
} 

「には、指定された条件を満たす、シーケンスの唯一の要素を返します。そのような要素が複数存在する場合は、 が例外をスローします。例外をスロー避けるためhttp://msdn.microsoft.com/en-us/library/bb535118.aspx

から

EDIT

、あなたもSingleOrDefault()メソッドを使用して:あなたはしないように

public bool ExistsUnique(Func<T, bool> p) 
{ 
    return myCollection.SingleOrDefault(x => p(x)) != null; 
} 
+0

これは素晴らしいアイデアです!私は同じ問題を抱えていましたが、同じ文字列の2つを追加しようとしてもtrueを返します。 – PNS

+0

例外をスローすることは必要ない場合はかなり遅く、例外なく同じことを行う簡単な方法がある場合は、このテクニックに注意してください。 –

+0

-1投げている例外を修正してください –

0

この実装はそれを作るだろうし実際にコレクション全体を列挙しなければならないので、実行時間を節約できます。

public bool ExistsUnique(Func<T, bool> p) 
{ 
    return MyCollection.Where(i => p(i)).Take(2).Count() == 1; 
} 

Take(2)のみ基準最初の二つの会議を列挙するCountを制限します。

関連する問題