2013-04-09 80 views
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 
+0

@jodha你没有创建一个列表。你只是使用'IEnumerable'。 – 2013-04-09 12:45:56

回答

11

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

为什么您的测试产量完全是随意的结果是这样的原因: 您列举每个集合三次:当你将它输出到控制台

  • 第二个枚举可能发生在测试

    1. 第一枚举发生AnyContains。因为这开始了一个新的枚举,所以会产生新的随机数。
    2. 第三次枚举发生在Intersect测试中。这创建了另一组随机数。

    为了解决这个问题,通过对GetCollection结果调用ToArray()创造一个稳定的序列。

  • +0

    伟大和感谢解释。 – JSJ 2013-04-09 13:01:05

    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()结果的引用,或者只是返回一个稳定的列表。