2012-09-11 3 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

リストとラムダの両方に 'a'を使用することはできません。 'a.Any(a => b.Contains(a))'。代わりにメソッドグループを使用することをお勧めします。 – radbyx

9

あなたは二つのリストIntersectことができます。

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

私はJustinsの2つのソリューションのプロファイルを作成しました。 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

私はそれを設定するためのより速い方法を書くことができます。しかし、私はいくつかのデータでそれをテストします。それは、ある程度高速ですが、Intersectは速いです。

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); 
    } 

交差は、第2のサイズをチェックしていない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を使用してカウントし、HashSetよりも高速であるIntersect使用setを確認しています。私たちはその性能を傷つけません。

テスト:

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

Countが要求されていません。これは非常に非効率的で、必須のコードです。 –

+0

ブール値の代わりにカウントを使用した理由など、この回答のための説明がもう少しあるかもしれません。これは仕事をやってもらう*。 – Taegost

関連する問題