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

Найти общие элементы в нескольких списках в С#

У меня есть два общих списка:

List<string> TestList1 = new List<string>();
List<string> TestList2 = new List<string>();
TestList1.Add("1");
TestList1.Add("2");
TestList1.Add("3");
TestList2.Add("3");
TestList2.Add("4");
TestList2.Add("5");

Каков самый быстрый способ найти общие элементы в этих списках?

4b9b3361

Ответ 1

Предполагая, что вы используете версию .Net с LINQ, вы можете использовать метод расширения Intersect:

var CommonList = TestList1.Intersect(TestList2)

Ответ 2

Если у вас есть списки объектов и вы хотите получить общие объекты для некоторого свойства, используйте:

var commons = TestList1.Select(s1 => s1.SomeProperty).ToList().Intersect(TestList2.Select(s2 => s2.SomeProperty).ToList()).ToList();

Примечание. SomeProperty ссылается на некоторые критерии, которые вы хотите реализовать.

Ответ 3

Предполагая, что у вас есть LINQ. Я не знаю, был ли он самым быстрым, но чистым способом было бы что-то вроде:

var distinctStrings = TestList1.Union(TestList2).Distinct();

Забастовкa >

var distinctStrings = TestList1.Union(TestList2);

Обновление: хорошо не помню моего ответа, я только что узнал об Intersect!

Согласно обновлению комментариев, Unions применяют отдельный, который имеет смысл теперь, когда я думаю об этом.

Ответ 4

Используйте метод Intersect:

IEnumerable<string> result = TestList1.Intersect(TestList2);

Ответ 5

Вы можете сделать это, посчитав вхождения всех элементов во всех списках - те элементы, число встречаемости которых равно количеству списков, являются общими для всех списков:

    static List<T> FindCommon<T>(IEnumerable<List<T>> lists)
    {
        Dictionary<T, int> map = new Dictionary<T, int>();
        int listCount = 0; // number of lists

        foreach (IEnumerable<T> list in lists)
        {
            listCount++;
            foreach (T item in list)
            {
                // Item encountered, increment count
                int currCount;
                if (!map.TryGetValue(item, out currCount))
                    currCount = 0;

                currCount++;
                map[item] = currCount;
            }
        }

        List<T> result= new List<T>();
        foreach (KeyValuePair<T,int> kvp in map)
        {
            // Items whose occurrence count is equal to the number of lists are common to all the lists
            if (kvp.Value == listCount)
                result.Add(kvp.Key);
        }

        return result;
    }

Ответ 6

Использование HashSet для быстрого поиска. Вот решение:

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

public class Program
{
    public static void Main()
    {
        List<int> list1 = new List<int> {1, 2, 3, 4, 5, 6 };
        List<int> list2 = new List<int> {1, 2, 3 };
        List<int> list3 = new List<int> {1, 2 };

        var lists = new IEnumerable<int>[] {list1, list2, list3 };

        var commons = GetCommonItems(lists);
        Console.WriteLine("Common integers:");
        foreach (var c in commons)
            Console.WriteLine(c);

    }

    static IEnumerable<T> GetCommonItems<T>(IEnumerable<T>[] lists)
    {
        HashSet<T> hs = new HashSet<T>(lists.First());
        for (int i = 1; i < lists.Length; i++)
            hs.IntersectWith(lists[i]);
        return hs;
    }
}

Ответ 7

Сортируйте оба массива и начните с вершины обоих и сравните, если они равны.


Использование хэша еще быстрее: поместите первый массив в хэш, затем сравните каждый элемент второго массива, если он уже находится в хеше.

Я не знаю, что эти Intersect и Union реализованы. Постарайтесь узнать их время работы, если вы заботитесь о производительности. Конечно, они лучше подходят, если вам нужен чистый код.