![](/img/trans.png)
[英]How to find common items across most lists [not all if can't] in C#
[英]Items Common to Most Lists
給定一個列表列表(假設有5個列表,要有一個可以使用的實數),我可以相對輕松地找到所有5個列表共有的項(參見使用IEnumerable.Intersect()的多個列表的交集 )以下代碼的變體:
var list1 = new List<int>() { 1, 2, 3 };
var list2 = new List<int>() { 2, 3, 4 };
var list3 = new List<int>() { 3, 4, 5 };
var listOfLists = new List<List<int>>() { list1, list2, list3 };
var intersection = listOfLists.Aggregate((previousList, nextList) => previousList.Intersect(nextList).ToList());
現在讓我們說intersection
最終包含0個項目。 很可能有一些對象是4/5列表中常見的。 我將如何以最有效的方式找到它們?
我知道我可以運行4個列表的所有組合並保存所有結果,但該方法不能很好地擴展(這最終必須在大約40個列表上完成)。
如果4個列表中沒有共同的項目,那么將重復搜索以查找3/5列表共有的項目等。在視覺上,這可以通過網格點列表來表示,我們正在搜索最多的點交疊。
有任何想法嗎?
編輯:也許最好是查看每個點並跟蹤它在每個列表中出現的次數,然后創建出現次數最多的點列表?
您可以從所有列表中選擇所有數字(點),並按值對其進行分組。 然后按組大小排序結果(即列出存在點的位數)並選擇最常見的項目:
var mostCommon = listOfLists.SelectMany(l => l)
.GroupBy(i => i)
.OrderByDescending(g => g.Count())
.Select(g => g.Key)
.First();
// outputs 3
您可以通過將Take(N)
替換為Take(N)
來取代First()
,而不是僅取第一項。
返回包含列表數量的項目(按列表數量排序):
var mostCommonItems = from l in listOfLists
from i in l
group i by i into g
orderby g.Count() descending
select new {
Item = g.Key,
NumberOfLists = g.Count()
};
用法(item是一個強類型的匿名對象):
var topItem = mostCommonItems.First();
var item = topItem.Item;
var listsCount = topItem.NumberOfLists;
foreach(var item in mostCommonItems.Take(3))
// iterate over top three items
您可以先組合所有列表,然后使用字典策略查找列表的模式,如下所示。 這使得它非常快:
/// <summary>
/// Gets the element that occurs most frequently in the collection.
/// </summary>
/// <param name="list"></param>
/// <returns>Returns the element that occurs most frequently in the collection.
/// If all elements occur an equal number of times, a random element in
/// the collection will be returned.</returns>
public static T Mode<T>(this IEnumerable<T> list)
{
// Initialize the return value
T mode = default(T);
// Test for a null reference and an empty list
if (list != null && list.Count() > 0)
{
// Store the number of occurences for each element
Dictionary<T, int> counts = new Dictionary<T, int>();
// Add one to the count for the occurence of a character
foreach (T element in list)
{
if (counts.ContainsKey(element))
counts[element]++;
else
counts.Add(element, 1);
}
// Loop through the counts of each element and find the
// element that occurred most often
int max = 0;
foreach (KeyValuePair<T, int> count in counts)
{
if (count.Value > max)
{
// Update the mode
mode = count.Key;
max = count.Value;
}
}
}
return mode;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.