2012-09-11 13 views

Odpowiedz

49

Jeśli nie dbają o wydajność, można spróbować:

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

Ale chciałbym spróbować ten pierwszy:

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

działa jak czar. Ponieważ jesteś pierwszym respondentem, więc zaznaczyłem twoją odpowiedź jako odpowiedź. Dzięki. – wahaha

+0

Nie można używać "a" zarówno jako listy, jak i w lambda. 'a.Any (a => b.Contains (a))'. Sugerowałbym użycie grupy metod zamiast 'a.Any (b.Contains)' – radbyx

11

Profilowałem Justinsa dwa rozwiązania. a.Any(a => b.Contains(a)) jest najszybszy.

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

napisać szybszy sposób można sprawić mały ustawić. Ale testuję to w niektórych danych, że jakiś czas jest szybszy, że przecinają się, ale jakiś czas przecinają szybko mój kod.

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

Przeciecie wzywa Set że nie sprawdzić drugi rozmiar i jest to kod Przeciecie za.

 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; 

Różnica dwóch metod jest moja metoda używać HashSet i sprawdzić liczbę i Intersect korzystanie set który jest szybszy niż HashSet. Nie prowadzimy działań wojennych.

Test:

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

Używam tego policzyć:

 int cnt = 0; 

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

Nie pyta się o liczbę. To bardzo nieefektywny, imperatywny kod. –

+0

W celu uzyskania tej odpowiedzi może być trochę więcej wyjaśnień, na przykład dlaczego wybrano opcję liczenia zamiast wartości boolowskiej. To * robi * wykonuje pracę. – Taegost

Powiązane problemy