2012-09-11 70 views

回答

49

如果你不關心性能,你可以嘗試:

a.Any(item => b.Contains(item)) 
// or, as in the column using a method group 
a.Any(b.Contains) 

但我想先試試這個:

a.Intersect(b).Any() 
+0

就像一個魅力。由於您是第一位答辯人,所以我將您標記爲答案。謝謝。 – wahaha

+0

你不能在列表和lambda中使用'a'。 'a。任何(a => b.Contains(a))''。我建議使用方法組而不是'a.Any(b.Contains)' – radbyx

9

可以Intersect兩個列表:

if (A.Intersect(B).Any()) 
11

我介紹了賈斯汀的兩個解決方案。 a.Any(a => b.Contains(a))最快的是

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace AnswersOnSO 
{ 
    public class Class1 
    { 
     public static void Main(string []args) 
     { 
//   How to check if list A contains any value from list B? 
//   e.g. something like A.contains(a=>a.id = B.id)? 
      List<int> a = new List<int> {1,2,3,4}; 
      List<int> b = new List<int> {2,5}; 
      int times = 10000000; 

      DateTime dtAny = DateTime.Now; 
      for (int i = 0; i < times; i++) 
      { 
       var aContainsBElements = a.Any(b.Contains); 
      } 
      var time = (DateTime.Now - dtAny).TotalSeconds; 

      DateTime dt2 = DateTime.Now; 
      for (int i = 0; i < times; i++) 
      { 
       var aContainsBElements = a.Intersect(b).Any(); 
      } 
      var time2 = (DateTime.Now - dt2).TotalSeconds; 

      // time1: 1.1470656 secs 
      // time2: 3.1431798 sec 
     } 
    } 
} 
0

我寫了一個更快的方法,它可以使小的設置。但是我在一些數據中測試它,一段時間以後相交會更快,但有一段時間與我的代碼快速交叉。

public static bool Contain<T>(List<T> a, List<T> b) 
    { 
     if (a.Count <= 10 && b.Count <= 10) 
     { 
      return a.Any(b.Contains); 
     } 

     if (a.Count > b.Count) 
     { 
      return Contain((IEnumerable<T>) b, (IEnumerable<T>) a); 
     } 
     return Contain((IEnumerable<T>) a, (IEnumerable<T>) b); 
    } 

    public static bool Contain<T>(IEnumerable<T> a, IEnumerable<T> b) 
    { 
     HashSet<T> j = new HashSet<T>(a); 
     return b.Any(j.Contains); 
    } 

相交調用Set尚未檢查第二尺寸,這是相交的代碼。

 Set<TSource> set = new Set<TSource>(comparer); 
     foreach (TSource element in second) set.Add(element); 
     foreach (TSource element in first) 
      if (set.Remove(element)) yield return element; 

兩種方法的區別是我的方法使用HashSet,檢查計數和Intersect使用setHashSet更快。我們不會對它的表現發火。

測試:

static void Main(string[] args) 
    { 
     var a = Enumerable.Range(0, 100000); 
     var b = Enumerable.Range(10000000, 1000); 
     var t = new Stopwatch(); 
     t.Start(); 
     Repeat(()=> { Contain(a, b); }); 
     t.Stop(); 
     Console.WriteLine(t.ElapsedMilliseconds);//490ms 

     var a1 = Enumerable.Range(0, 100000).ToList(); 
     var a2 = b.ToList(); 
     t.Restart(); 
     Repeat(()=> { Contain(a1, a2); }); 
     t.Stop(); 

     Console.WriteLine(t.ElapsedMilliseconds);//203ms 

     t.Restart(); 
     Repeat(()=>{ a.Intersect(b).Any(); }); 
     t.Stop(); 
     Console.WriteLine(t.ElapsedMilliseconds);//190ms 

     t.Restart(); 
     Repeat(()=>{ b.Intersect(a).Any(); }); 
     t.Stop(); 
     Console.WriteLine(t.ElapsedMilliseconds);//497ms 

     t.Restart(); 
     a.Any(b.Contains); 
     t.Stop(); 
     Console.WriteLine(t.ElapsedMilliseconds);//600ms 

    } 

    private static void Repeat(Action a) 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      a(); 
     } 
    } 
0

我用這個來算:

 int cnt = 0; 

     foreach (var lA in listA) 
     { 
      if (listB.Contains(lA)) 
      { 
       cnt++; 
      } 
     } 
+0

不要求計數。這是非常低效的命令式代碼。 –

+0

有一點更多的解釋可能是爲了這個答案,比如爲什麼你選擇使用計數而不是布爾值。這*確實*完成了工作。 – Taegost

相關問題