Подтвердить что ты не робот

Как проверить список A содержит любое значение из списка B?

Список A:

1, 2, 3, 4

Список B:

2, 5

Как проверить, содержит ли список A любое значение из списка B?

например. что-то вроде A.contains(a = > a.id = B.id)?

4b9b3361

Ответ 1

Если вы не заботитесь о производительности, вы можете попробовать:

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

Но я бы попробовал это первым:

a.Intersect(b).Any()

Ответ 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)?
            var a = new List<int> {1,2,3,4};
            var b = new List<int> {2,5};
            var times = 10000000;

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

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

            // timeAny: 1.1470656 secs
            // timeIn.: 3.1431798 secs
        }
    }
}

Ответ 3

Вы можете Intersect два списка:

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

Ответ 4

Я пишу более быстрый метод, чтобы он мог сделать маленький. Но я тестирую его в некоторых данных, что в какой-то момент это быстрее, чем 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);
    }

Intersect вызывает Set, которые не проверяют второй размер, и это код Intersect.

        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 и проверяет значение count и Intersect Set, которое быстрее, чем HashSet. Мы не защищаем его производительность.

Тест:

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

Ответ 5

Я использую это для подсчета:

int cnt = 0;

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

Ответ 6

Извините, если это неактуально, но вернет список совпадений, используя FindAll(), если вам это нужно:

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

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

И использование:

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

Окончательный список содержит только совпадающие элементы string1 и string2 из списка для проверки. Можно легко переключиться на Int List.