C# 在C中跨多个列表查找公共项#

C# 在C中跨多个列表查找公共项#,c#,generics,C#,Generics,我有两个通用列表: 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"); List

我有两个通用列表:

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");
List TestList1=newlist();
List TestList2=新列表();
测试列表1.添加(“1”);
测试列表1.添加(“2”);
测试列表1.添加(“3”);
测试列表2.添加(“3”);
测试列表2.添加(“4”);
测试列表2.添加(“5”);

在这些列表中查找常用项的最快方法是什么?

假设您使用的.Net版本具有LINQ,则可以使用Intersect扩展方法:

var CommonList = TestList1.Intersect(TestList2)

假设您有LINQ可用。我不知道这是不是最快的,但干净的方式应该是:

更新:不用管我的答案,我也刚刚了解了Intersect

根据评论中的一项更新,工会采用了一种截然不同的方式,现在我想这是有道理的。

使用以下方法:

IEnumerable result=TestList1.Intersect(TestList2);

对两个数组进行排序,从两个数组的顶部开始,比较它们是否相等


使用散列更快:将第一个数组放入散列,然后比较第二个数组中的每个项目(如果它已经在散列中)


我不知道那些Intersect和Union是如何实现的。如果您关心性能,请尝试了解他们的运行时间。当然,如果您需要干净的代码,它们更适合您。

您可以通过计算所有列表中所有项目的出现次数来做到这一点,这些项目的出现次数等于列表的数量,是所有列表的共同点:

    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;
    }
静态列表FindCommon(IEnumerable列表)
{
字典映射=新字典();
int listCount=0;//列表数
foreach(列表中的IEnumerable列表)
{
listCount++;
foreach(列表中的T项)
{
//遇到项目,增量计数
int currCount;
如果(!map.TryGetValue(项目,超出当前计数))
currCount=0;
currCount++;
映射[项目]=当前计数;
}
}
列表结果=新列表();
foreach(映射中的KeyValuePair kvp)
{
//出现次数等于列表数的项目对于所有列表都是公用的
if(kvp.Value==listCount)
结果.添加(kvp.Key);
}
返回结果;
}

如果您有对象列表,并且希望获得某些属性的公共对象,则使用

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

注意:SomeProperty指的是您想要实现的一些标准。

使用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;
    }
}
使用系统;
使用System.Linq;
使用System.Collections.Generic;
公共课程
{
公共静态void Main()
{
list1=新列表{1,2,3,4,5,6};
List list2=新列表{1,2,3};
List list3=新列表{1,2};
var list=new IEnumerable[]{list1,list2,list3};
var commons=GetCommonItems(列表);
Console.WriteLine(“公共整数:”);
foreach(公共空间中的var c)
控制台写入线(c);
}
静态IEnumerable GetCommonItems(IEnumerable[]列表)
{
HashSet hs=新的HashSet(lists.First());
for(int i=1;i
遵循@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();
列表l1、l2、l3、cmn;
列出所有;
l1=新列表(){1,2,3,4,5};
l2=新列表(){1,2,3,4};
l3=新列表(){1,2,3};
all=新列表(){l1,l2,l3};
cmn=all.SelectMany(x=>x).Distinct()
其中(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();
}
公共静态列表FindCommon(IEnumerable列表)
{
return list.SelectMany(x=>x).Distinct()
。其中(x=>列出。选择(y=>(y.Contains(x)?1:0))
.Sum()==Lists.Count()).ToList();
}

可能重复@Erno我看到了该线程,但我无法使用这些代码。事实上,这是一个好问题,是编译器错误还是您在调整它以适应代码方面遇到了问题?可能很重要,因为您尚未指定使用的.NET版本,我们似乎都认为您使用的是最新版本。@Adam Houldsworth我使用的是.NET 4@Erno,这个问题是关于列表选项列表的;我的问题是关于列表的,在那个问题中并没有人使用过Intersect方法。谢谢,但为什么是Ienumerable?我认为它应该是Ienumerable。@shaahin-是的-简单的打字。或者更好,因为C#3.0,使用
var
,让编译器保持原样。
Union
Intersect
已经包含了一个隐含的
Distinct
哇,很有趣,所以最后你不需要显式调用Distinct。我将修改我的答案。值得注意的是,
Union
将包括两个列表中的所有项目,而
Intersect
只获取出现在这两个列表中的项目。
Intersect
Union
Distinct
使用一个
HashSet
。这个函数是否与
var Common=List1.Intersect(List2)相同.Intersect(列表3)
或Intersect可能会因为不同时检查所有列表而中断,比如它会跳过其中任何一个吗?在我知道Intersect
var Common=Common.RemoveAll(I=>!List1.Contains(I))之前,我就使用了它;Common.RemoveAll(i=>!List2.Contains(i));=Common.RemoveAll(i=>!List3.Contains(i))
Common首先使用AddRange()由一个列表填充,然后对每个列表重复,我也无法打破它,但我有一种直觉认为它会打破。。
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;
    }
}
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();
}