簡體   English   中英

如何在C#中的大多數列表中找到通用項(如果不能,則不是全部)

[英]How to find common items across most lists [not all if can't] in C#

我有這樣的清單

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。

即使第3個列表不包含答案,它也應該得到答案0x670 ..因為它是大多數列表中唯一的一個。

從理論上講,如果第二個或第三個列表包含0x188 ,則最好使用它作為更好的答案,因為列表1中有很多它,並且它存在於2個列表中(大多數列表)。 但是它仍然應該給出兩個答案0x6700x188

如果列表2或列表3也包含0x188 ,那么答案應該有2個共同的答案。 0x6700x188

這是我以前使用的功能,但是它需要在所有列表中找到一個匹配項..但這並不總是可能的。

   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();
}

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()。

在此處輸入圖片說明

LasseVågsætherKarlsen的建議。 使用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
    ;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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