3
    [TestMethod()]
    public void TestExceptWithRandomInput()
    {
        byte[] listA =  new byte[4096];
        var rand = new Random();
        rand.NextBytes(listA);

        byte[] listB = new byte[] { 0x00 };
        var nullCount = (from a in listA
                         where a == 0x00
                         select a);

        var listC = listA.Except(listB);

        Assert.AreEqual(4096, listA.Length);
        Assert.AreEqual(4096 - nullCount.Count(), listC.Count()); //Fails!!
    }

    [TestMethod()]
    public void TestWhereWithRandomInput()
    {
        byte[] listA = new byte[4096];
        var rand = new Random();
        rand.NextBytes(listA);

        byte[] listB = new byte[] { 0x00 };
        var nullCount = (from a in listA
                         where a == 0x00
                         select a);

        var listC = listA.Where(a => !listB.Contains(a));

        Assert.AreEqual(4096, listA.Length);
        Assert.AreEqual(4096 - nullCount.Count(), listC.Count()); //Successful
    }

上記のコードは、Except()関数を使用すると失敗するように見えますが、Wh​​ere()を使用すると正常に機能します。何が欠けているようですか?バイト用にIEqualityComparerを実装する必要がありますか?それは複雑なタイプにのみ必要だと思いました。

4

2 に答える 2

7

Exceptまた、最初の引数の重複を取り除きます。これはセット操作であり、セットは重複することを意図していません-などと同じUnionです.Intersect

listA.Except(listB)内のすべての一意の null 以外のバイトを返しますlistA

シーケンス内のすべての非ヌルバイトを取得したい場合listA.Where(b => b != 0x00)は、おそらく論理的なことです。

null バイトをカウントしたい場合は、listA.Count(b => b == 0x00)これを最も明確に表現します。

「重複を除いて保存する」が!Contains必要な場合は、非常に効率的ではないすべてのアイテムを実行せずに、次のようにすることができます。

public static IEnumerable<T> ExceptWithDuplicates<T>(
    this IEnumerable<T> source1,
    IEnumerable<T> source2)
{
    HashSet<T> in2 = new HashSet<T>(source2);
    foreach(T s1 in source1)
    {
        if(!in2.Contains(s1)) // rather than if Add
        {
            yield return s1;
        }
    }
}

(免責事項: IDE で記述されていません。) これは基本的に通常の と同じですが、ソース項目を internalに追加Exceptしないため、同じ項目が複数回返されます。HashSet

于 2012-09-12T15:06:46.207 に答える
0

値のセットを返す以外は、すべての値を一度だけ返すことを意味します

于 2012-09-12T15:08:00.433 に答える