我有这样的列表
List<List<uint>> AllLists = new List<List<uint>>();
List<uint> TestList1 = new List<uint>();
List<uint> TestList2 = new List<uint>();
List<uint> TestList3 = new List<uint>();
TestList1.Add(0x18A);
TestList1.Add(0x188);
TestList1.Add(0x188);
TestList1.Add(0x188);
TestList1.Add(0x188);
TestList1.Add(0x188);
TestList1.Add(0x188);
TestList1.Add(0x670);
TestList2.Add(0x670);
TestList2.Add(0x670);
TestList3.Add(0xBADC0DE); //this one is empty.. but could contain some useless ones (not 0x670).
AllLists.Add(TestList1.ToList());
AllLists.Add(TestList2.ToList());
AllLists.Add(TestList3.ToList());
List<uint> MostCommonOffset = FindCommon(AllLists);
列表1具有:0x18A,0x188,0x188,0x188,0x188,0x188,0x188,0x670
列表2具有:0x670,0x670
列表3为0xBADC0DE。
它应该得到答案0x670
..即使第三个列表不包含答案,因为它是大多数列表中唯一的一个。
从理论上讲,如果第二个或第三个列表包含0x188
,则最好使用它作为更好的答案,因为列表1中有很多它。并且它存在于2个列表中(大多数列表)。但它仍应同时给出答案0x670
和0x188
。
如果列表2或列表3也包含0x188
,则答案应具有2个共同的答案。 0x670
和0x188
这是我以前使用的功能,但它需要在所有列表中找到一个匹配项。但这并不总是可能的。
public static List<T> FindCommon<T>(List<List<T>> lists)
{
//This checks to make sure all commons are the same in all lists.
List<uint> Counts = new List<uint>();
List<List<T>> Matches = new List<List<T>>();
bool Found = false;
//List<T> curCheck;
foreach (List<T> list in lists)
{
Found = false;
for (int i = 0; i < Counts.Count; i++)
{
if (Matches[i].Count == list.Count)
{
for (int j = 0; j < list.Count; j++)
{
//they not equals
if ((dynamic)Matches[i][j] != (dynamic)list[j])
goto next_loop;
//fully equal, increase count for repeated match found.
if (j == list.Count - 1)
{
Counts[i]++;
Found = true;
break;
}
}
}
next_loop:
if (Found) break;
continue;
}
if (!Found)
{
Counts.Add(1);
Matches.Add(list);
}
}
return Matches[Counts.IndexOf(Counts.Max())];
}
这是一种简单的方法,它可以检查所有列表,但不会检查所有列表中最常见的列表,如果不能,则不会检查所有列表。
public static List<T> FindCommon<T>(params List<T>[] lists)
{
//This checks to make sure all the commons that are partilly in all lists.
return lists
.SelectMany(x => x)
.Distinct()
.Where(item => lists.All(l => l.Contains(item)))
.ToList();
}
答案 0 :(得分:3)
LINQ解决方案有一些解释。也是LINQPad调试技巧。
List<List<uint>> AllLists = new List<List<uint>>();
List<uint> TestList1 = new List<uint>();
List<uint> TestList2 = new List<uint>();
List<uint> TestList3 = new List<uint>();
TestList1.Add(0x18A);
TestList1.Add(0x188);
TestList1.Add(0x188);
TestList1.Add(0x188);
TestList1.Add(0x188);
TestList1.Add(0x188);
TestList1.Add(0x188);
TestList1.Add(0x670);
TestList2.Add(0x670);
TestList2.Add(0x670);
TestList3.Add(0xBADC0DE); //this one is empty.. but could contain some useless ones (not 0x670).
AllLists.Add(TestList1.ToList());
AllLists.Add(TestList2.ToList());
AllLists.Add(TestList3.ToList());
var numbers = AllLists
.Select(x => x
.GroupBy(y => y) // group the numbers in each sub-list
.Select(z => new { Key = z.Key })) // select only the key in each sub-list
.SelectMany(x => x) // flatten the lists
.GroupBy(x => x.Key) // group by the keys
.OrderByDescending(x => x.Count()) // sort the count of keys from largest to smallest
;
var mostCount = numbers
.Select(x => x.Count()) // select the count of keys only
.Take(1) // take one, actually this line is not needed. you can remove it
.FirstOrDefault(); // take the largest count of key (the counts were sorted in previous linq statement)
var numberWithMostCount = numbers
.Where(x => x.Count() == mostCount) // filter the largest count of in the lists
.Select(x => x.Key) // select the key only
;
foreach (var n in numberWithMostCount)
Console.WriteLine(n); // print all key who has the largest count
您可能会注意到,在我先前的编辑中,我在LINQ语句中调用了一些Dump()方法。我在LinqPad中编写和调试了代码。它具有Dump()方法,可以轻松查看LINQ操作的结果。假设我在代码中放了一个Dump()方法(如果太小,请在新标签页中打开图片)。 Dump()方法显示LINQ方法的执行结果。您可以在每个Linq方法之后放置一个Dump()方法。尝试在任何带有注释的行中添加Dump()方法,最好一次添加一个或两个Dump()。
来自Lasse Vågsæther Karlsen的建议。使用Distinct()删除重复项。谢谢LasseVågsætherKarlsen。
var numbers = AllLists
.Select(x => x.Distinct()) // remove duplicates
.SelectMany(x => x) // flatten the lists
.GroupBy(x => x) // group by the keys
.OrderByDescending(x => x.Count()) // sort the count of keys from largest to smallest
;