【问题标题】:Select even/odd elements in IEnumerable<T>? [duplicate]在 IEnumerable<T> 中选择偶数/奇数元素? [复制]
【发布时间】:2012-06-29 22:44:11
【问题描述】:

可能重复:
Getting odd/even part of a sequence with LINQ
How can I get every nth item from a List<T>?

我正在使用 HtmlAgilityPack 和 C# 来解析一些 HTML。

<div id="post-8266">
<div class="ruler"> </div>
<div id="post-8266">
<div class="ruler"> </div>
<div id="post-8266">
<div class="ruler"> </div>
<div id="post-8266">
<div class="ruler"> </div>

基本上,我有这些元素,每个元素都在自己的对象中,在 IEnumerable 中。

有没有一种优雅的方式来获取集合中的每个 N/2 元素。意思是,跳过每个带有.ruler类的div?

我需要遍历结果集,因此要么将找到的每个对象复制到一个新的 IEnumerable 中,要么只在 foreach 函数中内联使用它。

例如:

//Copying resulting set to new IEnumerable<T>:
var odds = elements.SelectOdds();

//Using it inline for my usage:
foreach (var x in elements.SelectOdds())
{   
}

哪些选项最好,我怎样才能优雅地实现这一目标?

【问题讨论】:

标签: c# linq .net-4.0 ienumerable


【解决方案1】:
var odds = sequence.Where((item, index) => index % 2 != 0);
var evens = sequence.Where((item, index) => index % 2 == 0);

我不喜欢这个解决方案的唯一一点是,如果您需要赔率和偶数,它需要对序列进行两次迭代。如果由于某种原因您必须避免这种情况,您将不得不更加努力:

var groups = sequence.Select((item, index) => new { Item = item, Index = index })
                     .GroupBy(x => x.Index % 2 == 0)
                     .ToDictionary(g => g.Key, g => g);

那么,赔率是groups 的元素,其中Keyfalse,偶数是groups 的元素,其中Keytrue

var odds = groups[false];
var evens = groups[true];

【讨论】:

  • +1 我喜欢第二种方法背后的想法。但是,我真的很好奇这是否比简单版本更快。你不必枚举原始集合两次,但是随着匿名类型对象的创建、分组和字典的创建,我不知道这是否真的有回报......你怎么看?
  • @PhilipDaubmeier:我认为这取决于。如果你只从结果中得到Take(1000),第一种方法可能会更快,至少没关系。如果您愿意(例如使用Count()foreachToList()),Dictionary 方法可能会快得多。
  • 顺便说一下,Dictionary 方法会导致OutOfMemoryException 在具有 36GB ram 的 PC 上出现一个巨大的列表,而 double-Where 总是工作,如果你只取一个子集(fe Take(1000) 如上所述)。
  • @Philip Daubmeier:不枚举两次的原因通常不是速度,尽管这可能是一个合理的问题,但因为某些序列在迭代两次时不会产生相同的值。
  • @Jason:没错,这是一个好点。甚至可能出现第二个枚举产生相同值的情况,但确实(由于 linq 的延迟执行性质)会导致再次读取和解析整个 HTML 文件(例如)。结论:两种方法各有利弊,取决于具体的问题领域。
【解决方案2】:

您可以为此目的定义自己的扩展方法:

public static class LinqExtensions
{
    public static IEnumerable<T> SelectOdds<T>(this IEnumerable<T> enumerable)
    {
        bool odd = false;

        foreach (var item in enumerable)
        {
            if (odd)
                yield return item;

            odd = !odd;
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-11-26
    • 2014-01-17
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多