【问题标题】:Funky LINQ Required需要时髦的 LINQ
【发布时间】:2011-11-03 14:54:49
【问题描述】:

以下是我正在使用的 CSV 字符串。它实际上要大得多,但这足以显示一个模式。

请注意,我将这个 CSV 放在单独的行中只是为了方便地展示我的模式。

在 CSV 拆分后,字段的数量是可变的,具体取决于原始字符串的大小,即字符串的长度可变,这使得索引的数量可变

图案中的字母不一定都是P,可能是U、O或F

G9999999990001800002777107050,
G9999999990002777107HMNLAQKPRLLHRAQRWJ010,
1,
3,
29,
P,
6.74,
11.23,
07,
U,
5.25,
14.29,
08,
O,
6.89,
16.92,
07,
P,
5,
4,

我想选择第 5 个 (29) 和第 6 个 (P) 元素,然后错过 2 个元素,然后选择下一个元素 (07) 和 (P) 之后的一个元素,依此类推,直到我到达末尾字符串。

在这个例子中,我将 29 磷 07 磷 08 磷 07 P

有没有一种简单的方法可以做到这一点,我认为 LINQ 会提供一些东西

谢谢

【问题讨论】:

  • 你没有说你为什么想要这些元素。我猜规则是'所有元素要么是P,要么是P',但这只是一个猜测。如果第一个元素是 P 会发生什么?
  • 那是 CSV 吗?还是每个值都在新行上?注意:LINQ 并不是解决所有问题的灵丹妙药——如果数据如其所见,那么File.ReadAllLinesStreamReader 应该会有所帮助。
  • 抱歉,它是一个 CSV,我认为将它放在一个新行上可能会更好地展示我的示例。如果您愿意,我可以将其改回 CSV
  • @Jon: 谢谢你,不错的选择;但是,为了说明这一点,应该发表评论。你会相应地编辑问题吗?
  • 问题更新为粗体

标签: c# .net linq c#-4.0 .net-4.0


【解决方案1】:
line.Split(',')  //split on commas as it seems from your question that's your input
    .Skip(2) //skip the first two entries
    .Where((l, i) => i % 4 == 3 || i % 4 == 0) //take every 3rd and 4th item
    .Skip(1); //skip the first item since the index is divisible by 4

但这似乎根本无法描述代码在做什么,我至少要发表评论。

【讨论】:

  • 你能评论一下我不值得的眼睛吗,因为我不明白!
  • 这实际上不是关于线条...... OP已经澄清了
【解决方案2】:

http://ideone.com/EDof0

上的完整演示
using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static IEnumerable<int> SpecialIndexes()
    {
        int i=4; 

        while (i<Int32.MaxValue)
        {
            yield return i++;
            yield return i++;
            i += 2;
        }
    }

    public static void Main(string[] args)
    {
        var csvString = "G9999999990001800002777107050,G9999999990002777107HMNLAQKPRLLHRAQRWJ010,1,3,29,P,6.74,11.23,07,P,5.25,14.29,08,P,6.89,16.92,07,P,5,4,";

        var fields = csvString.Split(',');
        var selected = SpecialIndexes()
            .TakeWhile(i => i<fields.Length)
            .Select(i => fields[i]);

        Console.WriteLine(string.Join(" ", selected.ToArray()));
    }
}

输出:

29 P 07 P 08 P 07 P

【讨论】:

  • 我越来越确定我一定是被地狱禁止了。最近我的答案都没有得到任何关注:(
  • 公平地说,我真的不喜欢该范围的静态 100。我可能会选择Enumerable.Range(1, int.MaxValue - 1).SelectMany(...).TakeWhile(i =&gt; i is not outside string length)
  • @YuriyFaktorovich:我很肯定你没有尝试过
  • 我以前用过类似的东西。
  • 能不能先把 csvString 拆分,然后 Enumberable.Range 变成 Enumerable.Range(1,fields.length)
【解决方案3】:
string[] thestrings = source.Split(',');
string lastItem = thestrings.FirstOrDefault();
List<string> keepers = new List<string>();

foreach(string item in thestrings)
{
  if (item == "P")
  {
    if (lastItem != "P")
    {
      keepers.Add(lastItem);
    }
    keepers.Add(item);
  }
  lastItem = item;
}

【讨论】:

    【解决方案4】:

    我昨天做了类似的事情......这是我的代码

    //Create a new variable of string
    var x = string.Empty;
    //Open a new FileStream
    using (var fs = new FileStream(path,...))
    //Open the StreamReader
    using (var sr = new StreamReader(fs))
    {
    //Read out the whole CSV
       x = sr.ReadToEnd();
    }
    
    //Split up the string by ',' and whitespaces. dismiss empty entries
    var stringArray = x.Split(new char[] { ',', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries)
    
    //stolen code following 
    var myEnumerable = stringArray.Skip(2)
                                  .Where((item, index) => index % 4 == 3 || index % 4 == 0)
                                  .Skip(1);
    

    【讨论】:

    • 这类似于 Yuriy 的回答。你能解释一下发生了什么。我不太了解 mod 的东西,不要抱怨,但这不适用于我的 CSV
    • 解释了......对不起,我写了';'在拆分而不是 ',' 因为在我的程序中使用了 ';' :p 对此感到抱歉......希望能有一个上升 ;)
    【解决方案5】:

    要解析一行,我会使用 RegEx 而不是 Linq,因为它已编译并且速度更快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      相关资源
      最近更新 更多