簡體   English   中英

在 C# 中的多個列表中查找常見項目

[英]find common items across multiple lists in C#

我有兩個通用列表:

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

在這些列表中查找常見項目的最快方法是什么?

假設你使用的.Net版本有LINQ,你可以使用Intersect擴展方法:

var CommonList = TestList1.Intersect(TestList2)

如果您有對象列表並想要獲取某些屬性的通用對象,請使用;

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

注意: SomeProperty是指您要實現的一些標准。

假設您有 LINQ 可用。 我不知道它是否是最快的,但一個干凈的方式是這樣的:

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

var distinctStrings = TestList1.Union(TestList2);

更新:別介意我的回答,我也剛剛了解了相交!

根據評論中的更新,工會應用了一個獨特的,現在我想到它是有道理的。

您可以通過計算所有列表中所有項目的出現次數來做到這一點 - 出現次數等於列表數量的那些項目對所有列表都是通用的:

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

使用 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;
    }
}

使用Intersect方法:

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

對 arrays 進行排序,然后從兩者的頂部開始,比較它們是否相等。


使用 hash 甚至更快:將第一個數組放入 hash,然后比較第二個數組的每個項目,如果它已經在 hash 中。

我不知道那些 Intersect 和 Union 是否已實施。 如果您關心性能,請嘗試找出它們的運行時間。 當然,如果您需要干凈的代碼,它們更適合。

跟隨@logicnp 計算包含每個成員的列表數量,一旦你有了列表列表,這幾乎是一行代碼:

List<int> l1, l2, l3, cmn;
List<List<int>> all;

l1 = new List<int>() { 1, 2, 3, 4, 5 };
l2 = new List<int>() { 1, 2, 3, 4 };
l3 = new List<int>() { 1, 2, 3 };
all = new List<List<int>>() { l1, l2, l3 };

cmn = all.SelectMany(x => x).Distinct()
      .Where(x => all .Select(y => (y.Contains(x) ? 1 : 0))
      .Sum() == all.Count).ToList();

或者,如果您願意:

public static List<T> FindCommon<T>(IEnumerable<List<T>> Lists)
{
  return Lists.SelectMany(x => x).Distinct()
      .Where(x => Lists.Select(y => (y.Contains(x) ? 1 : 0))
      .Sum() == Lists.Count()).ToList();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM