在多个数组中找到最常见的元素组合

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", };

我如何获得所有数组中最常见的元素组合
在这种情况下,A和B是最常见的,因为它们出现在arr1,arr3和arr6中,并且C和D也是,因为它们出现在arr1,arr4和arr5中。
需要注意的是,元素可以在任何类型的集合中,例如ArrayLists中。 更新:哦,我表达不够清楚......是数组中两个元素最常见的组合。这就是我在示例中尝试展示但没有在问题中提到的内容。
很抱歉 :-((

定义最常见的是什么?前N个计数,至少存在Y次或者其他要求吗? - P.Brian.Mackey
1
"A"本身常见于数组1、2、3和6。同样,"B"出现在四个而不是三个数组中。为什么它们需要结合考虑呢? - Sergey Kalinichenko
你的问题不完整。你询问最常见的元素,但你的例子是关于元素对的。只考虑元素对吗?一个元素被认为是“最常见”的候选元素需要存在多少个实例?单个元素“A”在4个数组中。 - Charles Bretana
你计划拥有的集合数量是否有上限? - Sergey Kalinichenko
感谢您的更新,这解决了很多困惑。请查看我的更新答案以获取可行的解决方案。 - p.s.w.g
5个回答

5

如果你确定每个数组中的项目只出现一次,那么你可以把它们连接在一起并计算数量,例如:

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. 返回第一个配对

1
即使项目出现多次,您也可以使用SelectMany(a=>a.Distinct())来解决问题。尽管如此,我怀疑这不是OP想要的,因为如果他想要您的查询结果,他会谈论“ A”,“ B”和“ D”出现四次,而不是“ A”,“ B”出现三次。 - Sergey Kalinichenko

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

0
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}


0
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);

0

你的问题不够清晰,因为你没有明确定义你要寻找什么。一般来说,你可以将所有的数组合并成一个大数组,并计算出不同元素的数量。然后通过对元素进行排序,你可以对“最常见”的元素进行任何你想做的操作。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接