web-dev-qa-db-fra.com

Comment vérifier la liste A contient une valeur de la liste B?

Liste A: 

1, 2, 3, 4

Liste B: 

2, 5

Comment vérifier si la liste A contient une valeur de la liste B?

par exemple. quelque chose comme A.contains (a => a.id = B.id)?

38
wahaha

Si vous ne vous souciez pas de la performance, vous pouvez essayer:

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

Mais je voudrais essayer ceci en premier:

a.Intersect(b).Any()
69
Justin Niessner

J'ai présenté deux solutions à Justins.a.Any(a => b.Contains(a)) est le plus rapide .

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
        }
    }
}
16
radbyx

Vous pouvez Intersect les deux listes:

if (A.Intersect(B).Any())
12
D Stanley

J'utilise ceci pour compter:

int cnt = 0;

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

J'écris une méthode plus rapide pour que le petit soit paramétré. Mais je teste dans certaines données qu'il est parfois plus rapide que Intersect, mais que Intersect rapidement que mon code.

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

Les appels d'intersection Set qui n'ont pas vérifié la deuxième taille et il s'agit du code de l'intersection.

        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;

La différence entre deux méthodes est que ma méthode utilise HashSet et vérifie le nombre et Intersect utilise set qui est plus rapide que HashSet. Nous ne mettons pas en garde ses performances.

Le 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
lindexi

Désolé, si cela n'a pas d'importance, mais nous renverrons la liste avec les correspondances utilisant FindAll () au cas où vous en auriez besoin:

        private bool IsContain(string cont)
    {
        List<string> ListToMatch= new List<string>() {"string1","string2"};

        if (ListToMatch.ToArray().Any(cont.Contains))
        {
            return false;
        }
        else
            return true;
    }

Et utilisation:

List<string> ListToCheck = new List<string>() {"string1","string2","string3","string4"};
List<string> FinalList = ListToCheck.FindAll(IsContain);

La liste finale ne contient que les éléments correspondants string1 et string2 from list à vérifier . Peut facilement être basculé sur int List.

0
Atanas Atanasov