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

时间:2021-09-29 13:09:34

I have several arrays, like:

我有几个数组,比如:

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

... etc.

…等。

How can I get most common combination of elements in all of those arrays?

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

In this case it is A and B, because they occur in arr1, arr3 and arr6, and C and D, because they occur in arrays arr1, arr4 and arr5.

在这种情况下,它是A和B,因为它们发生在arr1、arr3和arr6、C和D,因为它们发生在arr1、arr4和arr5数组中。

Just to mention that elements can be in any kind of collection, ie. in ArrayLists also.

只要提到元素可以在任何类型的集合中。ArrayLists也。

UPDATE uuhhh, I was not clear enough...... Most common combinations of two elements in an array. That's what I tried to show in example, but did not mention in my question.

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

Sorry :-((

对不起:-(

5 个解决方案

#1


3  

If you are sure that each item appears only once in each array, you could just concatenate them together and get the counts, for example:

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

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

Or if you prefer query syntax, that would be:

或者如果您更喜欢查询语法,可以是:

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

The result set will contain 3 items:

结果集将包含3个项目:

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

Update

更新

Given your updated question, something like this should work:

考虑到你更新后的问题,类似这样的东西应该是有用的:

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

The logic here is:

这里的逻辑是:

  1. First find all distinct items in any array
  2. 首先在任何数组中查找所有不同的项
  3. Then find every pair of items to search for
  4. 然后找到每一对要搜索的条目
  5. Get of every pair, grouped by a list of what arrays contain that pair
  6. 获取每一对,按数组中包含的数组的列表进行分组
  7. Order by the groups by the number of arrays that contain each pair, descending
  8. 按组排序,按包含每对的数组的数量降序排列
  9. Return the first pair
  10. 返回第一对

#2


1  

use a Dictionary which will store an element as an index, and the occurrence count as a value. Iterate each list and count the occurrences.

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

#3


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

Gives you {A, 4}, {B, 4}, {D, 4}, {C, 3}

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

#4


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

#5


0  

Your question is unclear as you have not clearly defined what you are looking for. In general, you could combine all the arrays into one large array and count the distinct elements. By then ordering the elements you can do whatever you intend to do with the "most common".

你的问题不清楚,因为你还没有清楚地说明你在寻找什么。通常,您可以将所有数组组合成一个大数组,并计算不同的元素。然后排序元素,您就可以对“最常见的”元素做任何您想做的事情。

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

Outputs: A : 4, B : 4, D : 4, C : 3

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

#1


3  

If you are sure that each item appears only once in each array, you could just concatenate them together and get the counts, for example:

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

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

Or if you prefer query syntax, that would be:

或者如果您更喜欢查询语法,可以是:

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

The result set will contain 3 items:

结果集将包含3个项目:

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

Update

更新

Given your updated question, something like this should work:

考虑到你更新后的问题,类似这样的东西应该是有用的:

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

The logic here is:

这里的逻辑是:

  1. First find all distinct items in any array
  2. 首先在任何数组中查找所有不同的项
  3. Then find every pair of items to search for
  4. 然后找到每一对要搜索的条目
  5. Get of every pair, grouped by a list of what arrays contain that pair
  6. 获取每一对,按数组中包含的数组的列表进行分组
  7. Order by the groups by the number of arrays that contain each pair, descending
  8. 按组排序,按包含每对的数组的数量降序排列
  9. Return the first pair
  10. 返回第一对

#2


1  

use a Dictionary which will store an element as an index, and the occurrence count as a value. Iterate each list and count the occurrences.

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

#3


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

Gives you {A, 4}, {B, 4}, {D, 4}, {C, 3}

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

#4


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

#5


0  

Your question is unclear as you have not clearly defined what you are looking for. In general, you could combine all the arrays into one large array and count the distinct elements. By then ordering the elements you can do whatever you intend to do with the "most common".

你的问题不清楚,因为你还没有清楚地说明你在寻找什么。通常,您可以将所有数组组合成一个大数组,并计算不同的元素。然后排序元素,您就可以对“最常见的”元素做任何您想做的事情。

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

Outputs: A : 4, B : 4, D : 4, C : 3

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