合并、合并、相交 C# 对象列表

Merge, Union, Intersect C# List of Objects

我正在尝试解决这个问题:

我有多个字符串数组,其中一些有重复项。我需要提出一个最终列表,每个列表中包含最多的项目

a1 = Array{"A", "B", "C","D","E","F"}; 
a2 = Array{"A", "B", "B", "C","D","D","D","E","F"}; 
a3 = Array{"A", "B", "B", "C","D","D","E","F"};
a4 =  Array{"A", "B", "B", "B", "C","D","D","E","F"}; 
a5 = Array{"A", "B", "B", ","D","D","E","E","F"};

最终结果应该是:

FinalArray = {"A", "B", "B", "B", "C","D","D","D","E","E""F"};

最大。出现每一项都占最终结果。

我怎样才能做到这一点?

听起来像是一道作业题,所以我不确定你是否应该使用特定的 methods/logic 来解决它,但我会描述我将如何解决它。

分解问题。要求(据我所知)是显示每个值在任何一组中出现的最大次数。第一步是计算每个值在每个集合中出现的次数,这可以使用“GroupBy”然后使用“Count”聚合来完成:

aN.GroupBy( v => v )
    .Select( g => new
    {
        Value = g.Key,
        Count = g.Count(),
    } );

类似地,然后我们将结果组合成一个集合并按值对它们进行分组以获得用于生成结果集的“最大”计数值:

combinedResults.GroupBy( at => at.Value )
    .Select( g => new
    {
        Value = g.Key,
        Count = g.Max( at => at.Count ),
    } );

在继续之前,让我们合并前两个步骤,但在此之前,让我们将数组合并成它们自己的集合。

var sets = new List<IEnumerable<string>>    
{
    new string[]{ "A", "B", "C", "D", "E", "F" },
    new string[]{ "A", "B", "B", "C", "D", "D", "D", "E", "F" },
    ... etc ...
};

var valueMaxCounts = sets
    .Select( s =>
        s.GroupBy( v => v )
            .Select( g => new
            {
                Value = g.Key,
                Count = g.Count(),
            } ) )
    .GroupBy( at => at.Value )
    .Select( g => new
    {
        Value = g.Key,
        Count = g.Max( at => at.Count ),
    } );

所以现在我们有一组值,每个值在其中一个输入集中出现的最大次数。我们现在要遍历结果并将每个值相加 Count 次。

var resultList = new List<string>();

foreach( var vmc in valueMaxCounts )
{
    //for( var i = 0; i < vmc.Count; ++I )
    //{
    //    resultList.Add( vmc.Value );
    //}

    resultList.AddRange( Enumerable.Repeat( vmc.Value, vmc.Count ) );
}

查询和循环的最后 Select 可以替换为调用 SelectMany:

...query up to .GroupBy( at => at.Value )...
.SelectMany( g => Enumerable.Repeat( g.Key, g.Max( at => at.Count ) ) )

解决这个问题的一个简单方法是先创建一个列表来存储结果,然后遍历每个数组中的唯一项,并将当前数组中的项数与计数之差相加结果中的项目数(如果是正数)。

例如:

var arrays = new[]
{
    new[] {"A", "B", "C", "D", "E", "F"},
    new[] {"A", "B", "B", "C", "D", "D", "D", "E", "F"},
    new[] {"A", "B", "B", "C", "D", "D", "E", "F"},
    new[] {"A", "B", "B", "B", "C", "D", "D", "E", "F"},
    new[] {"A", "B", "B", "C", "D", "E", "E", "F"},
};

var result = new List<string>();

foreach (var array in arrays)
{
    var distinctItems = array.Distinct();

    foreach (var distinctItem in distinctItems)
    {
        var diff = array.Count(i => i == distinctItem) - 
                   result.Count(i => i == distinctItem);

        if (diff > 0) result.AddRange(Enumerable.Repeat(distinctItem, diff));
    }
}

Console.WriteLine(string.Join(", ", result.OrderBy(i => i)));

输出

简单。

var arrays = new[]
{
    new[] {"A", "B", "C", "D", "E", "F"},
    new[] {"A", "B", "B", "C", "D", "D", "D", "E", "F"},
    new[] {"A", "B", "B", "C", "D", "D", "E", "F"},
    new[] {"A", "B", "B", "B", "C", "D", "D", "E", "F"},
    new[] {"A", "B", "B", "C", "D", "E", "E", "F"},
};

var result =
    arrays
        .SelectMany(xs => xs.GroupBy(x => x).Select(x => new { x.Key, Count = x.Count() }))
        .GroupBy(x => x.Key, x => x.Count)
        .Select(x => new { x.Key, Count = x.Max() })
        .SelectMany(x => Enumerable.Repeat(x.Key, x.Count))
        .ToArray();

这给出:A, B, B, B, C, D, D, D, E, E, F