2

我想比较两个列表。我想检查 List2 是否有 List1 中的任何项目。我得到了意想不到的结果。请在下面查看我的代码。

测试代码类

class Program
{
    static void Main(string[] args)
    {
        bool loop = true;
        int textcount = 1;
        while (loop)
        {

            var collection1 = GetCollection();
            var collection2 = GetCollection();

            Console.WriteLine("Test No " + textcount.ToString());


            Console.WriteLine("Collection 1 =" + String.Join(", ", collection1.ToArray()));

            Console.WriteLine("Collection 2 =" + String.Join(", ", collection2.ToArray()));

            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            var hasitem = collection1.Any(item => collection2.Contains(item));

            watch.Stop();

            Console.WriteLine(hasitem.ToString() + "  Found in " + watch.ElapsedTicks.ToString());
            watch.Reset();

            watch.Start();
            var hasAtLeastOne = collection1.Intersect(collection2).Any();
            watch.Stop();
            Console.WriteLine(hasAtLeastOne.ToString() + "  With Intersect Found in " + watch.ElapsedTicks.ToString());
            textcount++;
            Console.ReadKey();
        }


    }
    static Random ran = new Random();
    private static IEnumerable<int> GetCollection()
    {
        for (int i = 0; i < 5; i++)
        {
            yield return ran.Next(i, 20);
        }
    }
}

结果很烦人。查看最后 4 个结果。

Test No 1
Collection 1 =10, 8, 18, 6, 11
Collection 2 =3, 12, 18, 13, 6
True  Found in 3075
True  With Intersect Found in 15297
 Test No 2
Collection 1 =18, 13, 7, 18, 5
Collection 2 =12, 18, 8, 3, 5
True  Found in 22
True  With Intersect Found in 100
 Test No 3
Collection 1 =1, 6, 15, 7, 9
Collection 2 =16, 15, 14, 14, 12
True  Found in 21
True  With Intersect Found in 23
 Test No 4
Collection 1 =3, 16, 7, 4, 19
Collection 2 =6, 3, 15, 15, 9
True  Found in 21
True  With Intersect Found in 56
 Test No 5
Collection 1 =18, 18, 9, 17, 10
Collection 2 =17, 12, 4, 3, 11
True  Found in 25
True  With Intersect Found in 20
 Test No 6
Collection 1 =9, 9, 2, 17, 19
Collection 2 =17, 2, 18, 3, 15
False  Found in 109
False  With Intersect Found in 41
 Test No 7
Collection 1 =3, 15, 3, 5, 5
Collection 2 =2, 2, 11, 7, 6
True  Found in 22
False  With Intersect Found in 15
 Test No 8
Collection 1 =7, 14, 17, 14, 18
Collection 2 =18, 4, 7, 18, 16
False  Found in 28
True  With Intersect Found in 19
 Test No 9
Collection 1 =3, 9, 6, 18, 9
Collection 2 =10, 3, 17, 17, 18
True  Found in 28
True  With Intersect Found in 22
 Test No 10
Collection 1 =15, 18, 2, 9, 8
Collection 2 =10, 15, 3, 10, 19
False  Found in 135
True  With Intersect Found in 128
 Test No 11
Collection 1 =6, 2, 17, 18, 18
Collection 2 =14, 16, 14, 6, 4
False  Found in 20
False  With Intersect Found in 17
4

2 回答 2

11

问题是你所说的“集合”实际上是一个不稳定的项目序列,每次枚举时都会发生变化。原因是您实施的方式GetCollection。使用yield return基本上会返回有关如何创建序列的蓝图。它不返回序列本身。
因此,每次枚举“蓝图”时,它都被用来创建一个新序列。您可以通过简单地输出您的“收藏”两次来验证这一点。您将看到每次的值都不同。

这就是您的测试产生完全任意结果的原因:您将每个集合枚举三遍:

  1. 当您将其输出到控制台时会发生第一次枚举
  2. 第二次枚举发生在使用 and 的测试AnyContains。因为这会开始一个新的枚举,所以会生成新的随机数。
  3. 第三次枚举发生在Intersect测试中。这会创建另一组随机数。

要修复它,请通过调用ToArray().GetCollection

于 2013-04-09T12:46:38.537 回答
0

这是你的问题:

private static IEnumerable<int> GetCollection()
{
    for (int i = 0; i < 5; i++)
    {
        yield return ran.Next(i, 20);
    }
}

把它变成这样:

private static List<int> GetCollection()
{
  return new List<int>
         {
           ran.Next(0, 20),
           ran.Next(1, 20),
           ran.Next(2, 20),
           ran.Next(3, 20),
           ran.Next(4, 20)
         };
}

你的问题就会消失。

冗长的解释是,当您创建一个 IEnumerable 函数时,您可以期望它在各种 LINQ 调用上重复调用迭代器(毕竟,这就是 IEnumerable 所做的,对吧?)。由于您yield return <some random number>对每个迭代器调用都执行一次,因此您可能会得到不稳定的结果。最好保存对.ToArray()结果的引用,或者只返回一个稳定的列表。

于 2013-04-09T13:08:15.110 回答