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可能会因为不同时检查所有列表而中断,比如它会跳过其中任何一个吗?在我知道Intersectvar 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();
}