代码之家  ›  专栏  ›  技术社区  ›  SSpoke

如何在C语言中的大多数列表(如果不能,则不是所有列表)中找到公共项#

  •  -1
  • SSpoke  · 技术社区  · 6 年前

    我有这样的清单

    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

    列表3是0xBADC0DE。

    它应该得到答案 0x670 .. 即使第三个列表没有包含它,因为它是大多数列表中唯一存在的列表。

    理论上,如果第二个或第三个列表包含 0x188 这是一个更好的答案,因为在列表1中有很多。。它存在于两个列表中(大多数列表)。但它仍然应该给出这两个答案 0x670 0x188 .

    如果列表2或列表3也包含 0x188 ,那么答案应该有两个共同点。 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();
    }
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   Han    6 年前

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

    enter image description here

    Lasse VÃ¥gsæther Karlsen . 使用Distinct()删除重复项。谢谢,拉丝·维格瑟·卡尔森。

    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
        ;