【问题标题】:Merge, Union, Intersect C# List of Objects [closed]合并,联合,相交 C# 对象列表 [关闭]
【发布时间】:2019-03-09 06:29:35
【问题描述】:

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

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

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

最大。发生在最终结果中的每个项目。

我怎样才能做到这一点?

【问题讨论】:

  • 您如何确定您保留哪些数组中的哪些项目?另外,到目前为止,您尝试过什么?
  • @John 请注意,a5 甚至无法编译
  • 您的代码无法编译...

标签: c# list linq c#-4.0 ienumerable


【解决方案1】:

听起来像是一个家庭作业问题,所以我不确定你是否应该使用特定的方法/逻辑来解决它,但我会描述我将如何解决它。

分解问题。要求(据我所知)是显示每个值在任何一组中出现的最大次数。第一步是计算每个值在每个集合中出现的次数,这可以使用“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 ) ) )

【讨论】:

    【解决方案2】:

    简单。

    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

    【讨论】:

    • 感谢您的解决方案。
    【解决方案3】:

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

    例如:

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

    输出

    【讨论】:

    • 感谢您的解决方案。
    猜你喜欢
    • 2015-07-31
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 2021-11-13
    • 2013-11-26
    • 2019-06-09
    相关资源
    最近更新 更多