【问题标题】:Performing a type of union of two IEnumerable collections执行两个 IEnumerable 集合的联合类型
【发布时间】:2010-10-24 13:30:08
【问题描述】:

假设您有两个整数集合:

IEnumerable<int> col1=new List<int> {2,3,3,5,7,11,11,11,13};
IEnumerable<int> col2=new List<int> {5,7,7,7,11,19};

现在我想创建第三个集合col3,这样对于出现在col1col2 中的每个不同元素,col3 将包含至少与col1 或 col2 中元素的最大出现次数,但仅此而已。让我展示最终结果,然后再详细说明:

   IEnumerable<int> col3=...;

col3 的内容应该是:

{2,3,3,5,7,7,7,11,11,11,13,19}

将 col3 的内容描述为这种“伪联合”操作的结果的另一种方法是,它应该包含每个值的足够元素,但不能更多,这样两个原始集合中的任何一个都可以单独形成(即,一次一个,从 col3 中的整个数字域)通过从 col3 中提取元素。

如果我所说的“一次一个”的意思仍然令人困惑,请想象col1col2 是不同类型的弹珠的集合,有重复。我想形成col3,这样我就有最少数量的不同类型的弹珠,这样我就可以从col3中取出足够的弹珠以形成col1,然后将弹珠放回col3,然后删除足够的弹珠形成col2

如果答案使用 LINQ 提出解决问题的单个表达式,我会很高兴,因为到目前为止我想到的两种方法涉及:

  1. 合并包含直方图(即每个不同整数的出现次数)的字典。
  2. col1 构造一个字典,然后在处理col2 的同时执行“标记和插入”类型的操作,从而生成一个最终字典,其中每个整数的计数刚好满足我的标准。

更新:保证输入集合是有序的(即单调且非递减的)并且结果集合应该是相同的顺序。

【问题讨论】:

    标签: c# visual-studio-2010 .net-4.0 c#-4.0


    【解决方案1】:

    像这样:

    var groups1 = col1.ToLookup(e => e);
    var groups2 = col2.ToLookup(e => e);
    
    var col3 = col1.Union(col2)
                   .SelectMany(e => Enumerable.Repeat(e, 
                       Math.Max(
                                groups1[e].Count(), 
                                groups2[e].Count()
                       )
                    ));
    

    【讨论】:

    • 看来问题解决了。我想知道如果没有两组中间变量,是否有任何方法可以做到这一点。
    • @Michael:不是不写循环。 (可能在自定义扩展方法中)
    • 好吧,我想您可以用它们的形成代码(即 col1.ToLookup(e => e))替换 groups1/groups2,但这将是低效的,因为它们将在 SelectMany 的每次迭代中重新创建
    • @Michael:你可以写col1.Count(c =&gt; c == e),这样效率会稍微低一些。
    • 是的,但它也相当于在每个集合中对每个计​​数进行线性搜索,而不是希望在 groups1 字典中进行对数(或恒定时间,如果它们是哈希)查找。
    猜你喜欢
    • 2018-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-23
    • 2017-05-19
    • 2010-10-10
    • 2013-11-12
    • 2011-07-25
    相关资源
    最近更新 更多