【问题标题】:Find most common combination of elements in several arrays查找多个数组中最常见的元素组合
【发布时间】:2013-11-15 00:39:25
【问题描述】:

我有几个数组,比如:

var arr1 = new[] { "A", "B", "C", "D" };
var arr2 = new[] { "A", "D" };
var arr3 = new[] { "A", "B", };
var arr4 = new[] { "C", "D" };
var arr5 = new[] { "B", "C", "D" };
var arr6 = new[] { "B", "A", };

...等等

如何获得所有这些数组中最常见的元素组合

在本例中是 A 和 B,因为它们出现在 arr1、arr3 和 arr6 中,而 C 和 D,因为它们出现在数组 arr1、arr4 和 arr5 中。

只是提到元素可以在任何类型的集合中,即。在 ArrayLists 中也是如此。

更新 uuhhh,我不够清楚...... 两个元素在数组中的最常见组合。这就是我试图在示例中展示的内容,但在我的问题中没有提及。

对不起 :-((

【问题讨论】:

  • 定义最常见的。前 N 个计数,至少存在 Y 次还是什么?
  • "A" 本身对于数组 1、2、3 和 6 是通用的。"B" 也是如此,它出现在四个而不是三个数组中。为什么需要结合起来考虑?
  • 您的问题不完整。您询问最常见的元素,但您的示例是关于元素对。是否只考虑元素对?一个元素必须存在多少个实例才能被视为“最常见”的候选者?单个元素“A”在 4 个数组中。
  • 您计划拥有的收藏数量是否有上限?
  • 感谢更新,解决了很多困惑。请参阅我的更新答案以获取有效的解决方案。

标签: c# arrays


【解决方案1】:

如果您确定每个项目在每个数组中只出现一次,您可以将它们连接在一起并获取计数,例如:

var arrs = new[] { arr1, arr2, arr3, arr4, arr5, arr6 };
var intermediate = arrs.SelectMany(a => a)
                       .GroupBy(x => x)
                       .Select(g => new { g.Key, Count = g.Count() })
                       .OrderByDescending(x => x.Count);
var maxCount = intermediate.First().Count;
var results = intermediate.TakeWhile(x => x.Count == maxCount);

或者,如果您更喜欢查询语法,那就是:

var arrs = new[] { arr1, arr2, arr3, arr4, arr5, arr6 };
var intermediate = 
    from a in arrs.SelectMany(a => a)
    group a by a into g
    orderby g.Count() descending
    select new { g.Key, Count = g.Count() };
var maxCount = intermediate.First().Count;
var results = intermediate.TakeWhile(x => x.Count == maxCount);

结果集将包含 3 个项目:

Key, Count
"A", 4 
"B", 4 
"D", 4 

更新

鉴于您更新的问题,这样的事情应该可以工作:

var items = arrs.SelectMany(a => a).Distinct();
var pairs =
    from a in items
    from b in items
    where a.CompareTo(b) < 0
    select new { a, b };
var results = 
    (from arr in arrs
     from p in pairs 
     where arr.Contains(p.a) && arr.Contains(p.b)
     group arr by p into g
     orderby g.Count() descending
     select g.Key)
    .First();

这里的逻辑是:

  1. 首先在任意数组中找到所有不同的项
  2. 然后找到每一对要搜索的项目
  3. 获取每对,按包含该对的数组列表分组
  4. 按包含每对的数组数量按组排序,降序
  5. 返回第一对

【讨论】:

  • 即使项目出现多次,您也可以使用SelectMany(a=&gt;a.Distinct()) 来解决问题。 I doubt that that is what the OP is after, though,因为如果他想要您的查询给出的内容,他会谈论出现四次的"A""B""D",而不是出现三次的"A","B"
【解决方案2】:

使用字典,它将元素存储为索引,并将出现次数存储为值。迭代每个列表并计算出现次数。

【讨论】:

    【解决方案3】:
    var arr1 = new[] { "A", "B", "C", "D" };
    var arr2 = new[] { "A", "D" };
    var arr3 = new[] { "A", "B", };
    var arr4 = new[] { "C", "D" };
    var arr5 = new[] { "B", "C", "D" };
    var arr6 = new[] { "B", "A", };
    
    var results = new List<IEnumerable<string>>() { arr1, arr2, arr3, arr4, arr5, arr6 }
                                    .Select(arr => arr.Distinct())
                                    .SelectMany(s => s)
                                    .GroupBy(s => s)
                                    .Select(grp => new { Text = grp.Key, Count = grp.Count() })
                                    .OrderByDescending(t => t.Count)
                                    .ToList();
    

    给你 {A, 4}, {B, 4}, {D, 4}, {C, 3}

    【讨论】:

      【解决方案4】:
      var result = new IEnumerable<String>[] {arr1, arr2, arr3, arr4, arr5, arr6}
                      .SelectMany(a => a)
                      .GroupBy(s => s)
                      .GroupBy(g => g.Count())
                      .OrderByDescending(g => g.Key)
                      .FirstOrDefault()
                      .SelectMany(g => g.Key);
      

      【讨论】:

        【解决方案5】:

        您的问题不清楚,因为您没有明确定义您要查找的内容。通常,您可以将所有数组组合成一个大数组并计算不同的元素。通过然后对元素进行排序,您可以对“最常见”的元素做任何您想做的事情。

        static void Main()
        {
            var arr1 = new[] { "A", "B", "C", "D" };
            var arr2 = new[] { "A", "D" };
            var arr3 = new[] { "A", "B", };
            var arr4 = new[] { "C", "D" };
            var arr5 = new[] { "B", "C", "D" };
            var arr6 = new[] { "B", "A", };
            List<string> combined = Combine(arr1, arr2, arr3, arr4, arr5, arr6);
        
            var ordered = combined.OrderBy(i => i);//sorted list will probably help other functions work more quickly such as distinct
            var distinct = ordered.Distinct();
        
            var counts = new Dictionary<string, int>();
        
            foreach (var element in distinct)
            {
                var count = ordered.Count(i => i == element);
                counts.Add(element, count);
            }
        
            var orderedCount = counts.OrderByDescending(c => c.Value);
        
            foreach (var count in orderedCount)
            {
                Console.WriteLine("{0} : {1}", count.Key, count.Value);
            }
            Console.ReadLine();
        }
        
        private static List<string> Combine(string[] arr1, string[] arr2, string[] arr3, string[] arr4, string[] arr5, string[] arr6)
        {
            List<string> combined = new List<string>();
            combined.AddRange(arr1);
            combined.AddRange(arr2);
            combined.AddRange(arr3);
            combined.AddRange(arr4);
            combined.AddRange(arr5);
            combined.AddRange(arr6);
            return combined;
        }
        

        输出:A:4,B:4,D:4,C:3

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-01-24
          • 1970-01-01
          • 2019-10-16
          • 2015-02-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多