【问题标题】:Applying "where" clause (LINQ) on even rows only [C#]仅在偶数行上应用“where”子句 (LINQ) [C#]
【发布时间】:2016-05-15 00:01:31
【问题描述】:

我有一个字符串,在交替的行中有两种不同类型的数据(即两行记录一个记录)。我只想选择第二个(即偶数行)长度小于 1000 的记录。

我已经尝试过了,但结果是只选择了偶数行并丢弃了奇数行:

var lessthan1000Length = recordsFile.Where((src, index) => src.Length<1000 && index%2 != 0);

来自 recordsFile 的样本数据

2012-12-04 | 10:45 AM | Lahore
Added H2SO4 in the solution. Kept it in the lab temperature for 10 minutes    
2012-12-04 | 10:55 AM | Lahore
Observed the pH of the solution.     
2012-12-04 | 11:20 AM | Lahore
Neutralized the solution to maintain the pH in 6-8 range

感谢您的指导。

P.S:请注意,结果需要以List&lt;string&gt; 的形式提供,因为我们必须从中创建一个新数据集。

【问题讨论】:

  • 所以改用index%2 != 0?它从第 0 个开始,而不是第 1 个(从零开始的索引)。
  • @JeppeStigNielsen 使用!= 或`==',这并不重要,因为它开始分别只选择偶数行,奇数行。我想要记录的两行。请注意,奇数行和偶数行合并形成一个记录。例如,第 353 行和第 354 行一起构成一条记录。我无法从中选择任何一行
  • 样本数据似乎每条记录使用三行(每三行记录一个空行)。这是正确的还是你刚刚发布的?
  • @Enigmativity 对不起!它不是 3 行。我就是这样发的。
  • 啊,我没有立即理解您想要将条目“配对”以使前两个条目放在一起,依此类推。它让我想起了Split an IEnumerable&lt;T&gt; into fixed-sized chunks (return an IEnumerable&lt;IEnumerable&lt;T&gt;&gt; where the inner sequences are of fixed length) duplicate 之类的线程。然而,当我们只想要长度为 2(对)的“块”时,它可能会更简单。

标签: c# linq


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

var records = odds.Zip(evens, (odd, even) => new { odd, even })
    .Where(pair => pair.even.Length < 1000);

foreach (var record in records)
    Console.WriteLine(record);

【讨论】:

  • 非常感谢亚历山大。有一个问题是我想选择这些记录并将其放入另一个数据集中,因此我需要它们以字符串的形式出现(List&lt;string&gt; 最好),但它不允许我将“记录”转换为列表。你能指导一下吗?
  • 不应该反过来吗?偶数是 0,2,4, ...我认为模数必须为 0 偶数而不是赔率
【解决方案2】:
List<string> result = recordFile
  .Select( (str, index) => new {str, index})
  .GroupBy(x => x.index / 2, x => x.str)
  .Where(g => g.Last().Length < 1000)
  .Select(g => g.First() + g.Last())
  .ToList();

【讨论】:

    【解决方案3】:

    Alexander 的回答似乎很好。

    或者,您可以创建一种方法来将序列(具有偶数项)转换为对序列。我猜是这样的:

    static IEnumerable<Tuple<T, T>> PairUp<T>(this IEnumerable<T> src)
    {
      using (var e = src.GetEnumerator)
      {
        while (e.MoveNext())
        {
          var first = e.Current;
    
          if (!e.MoveNext())
            throw new InvalidOperationException("Count of source must be even"); // OR: yield break; OR yield return Tuple.Create(first, default(T)); yield break;
          var second = e.Current;
    
          yield return Tuple.Create(first, second);
        }
      }
    }
    

    你可以这样做 recordsFile.PairUp().Where(t =&gt; t.Item2.Length &lt; 1000) 或类似的。

    编辑:由于您希望将两个“部分”连接为字符串,因此应为 recordsFile.PairUp().Where(t =&gt; t.Item2.Length &lt; 1000).Select(t =&gt; t.Item1 + t.Item2)。

    【讨论】:

    • 谢谢杰普。亚历山大的回答几乎是完美的。只是问题在于恢复字符串
    【解决方案4】:

    如果您使用 Microsoft 的 Reactive Framework 团队的“交互式扩展”,您将获得一个可以帮助您的不错的扩展方法。

    var query = 
        from pair in lines.Buffer(2)
        where pair[1].Length < 1000
        select pair;
    
    var results = query.ToList();
    

    从您的示例数据中我得到:

    只需 NuGet "Ix-Main" 即可获取扩展方法 - 除了 .Buffer 之外,还有很多其他方法,其中许多都非常有用。

    【讨论】:

    • 谢谢。这对我来说是新事物。 Insha'Allah 我一定会调查的。但请记住,我们需要成对返回。不只是连线。请相应更新
    • @TalhaIrfan - 我已经更新了答案以撤回对。现在更简单了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    相关资源
    最近更新 更多