簡體   English   中英

大多數列表共有的項目

[英]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.

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