【问题标题】:Please Explain this C# LINQ statement请解释这个 C# LINQ 语句
【发布时间】:2019-12-30 03:02:33
【问题描述】:

前段时间我在 stackoverflow 上找到了这段代码,但似乎再也找不到了。所有功劳归于作者。抱歉,我无法链接。

QUESTION? 一些 C# LINQ 大师能否逐步分解这个陈述,因为我很难理解它。它确实运作良好并且可以完成工作,但是如何?

要拆分的行

var line = $"13351.750815 26646.150876 6208.767863 26646.150876 1219.200000 914.400000 0.000000 1 \"Beam 1\" 0 1 1 1 0 1 1e8f59dd-142d-4a4d-81ff-f60f93f674b3";
var splitLineResult = line.Trim().Split('"')
                                    .Select((element, index) => index % 2 == 0
                                    ? element.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                                    : new string[] { element })
                                    .SelectMany(element => element).ToList();

LinqPad 中的语句结果

【问题讨论】:

  • 老实说,人们已经解释了代码的作用,但它不需要做所有的体操。目标是从一长串中取出所有项目。我会简单地这样做:1)使用引号分割整个事物 2)使用空格分割第一部分 3)使用空格分割最后一部分 4)连接结果。简单的! Check it Out.

标签: c# linq


【解决方案1】:

您需要首先分析您手头的输入。

13351.750815 26646.150876 6208.767863 26646.150876 1219.200000 914.400000 0.000000 1 "Beam 1" 0 1 1 1 0 1 1e8f59dd-142d-4a4d-81ff-f60f93f674b3

输入由几个由空格分隔的字母数字字符串组成。但是,还有一种特殊情况也需要处理。 引号中包含“Beam 1”一词。

现在,让我们分解一下 Linq 语句。

 line.Trim().Split('"')

第一个语句根据分隔符 Quotes 拆分输入。这会将字符串分成 3 部分。

如您所见,first(in 0th Index) 和 Last(in index position 2) 需要进一步拆分,而 in index 位置的元素1 已被解析。这就是 Linq 语句的第二部分出现的地方。

.Select((element, index) => index % 2 == 0
                                    ? element.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                                    : new string[] { element })

在上述语句中,Select((element, index) => index % 2 == 0 部分检查当前索引位置是否处于偶数位置。如果是这样,则需要根据分隔符' ' (whitespace) 进一步拆分子字符串。否则,它会创建一个包含单个实体“Beam 1”的数组

在第二部分的最后,你得到的是一个包含 3 个字母数字字符串的子集合 (IEnumerble<string[]>)。

现在需要做的是通过展平父集合来创建一个集合。这是使用Enumerable.SelectMany 完成的。

.SelectMany(element => element).ToList();

希望这有助于更好地理解 Linq 查询

【讨论】:

  • What now needs to be done is create a collection by **joining** these collection,未加入,展平
  • parent 集合被展平,但子集合被有效连接。
【解决方案2】:

拆分声明


    var splitLineResult = line.Trim().Split('"')
                            .Select((element, index) => index % 2 == 0
                            ? element.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                            : new string[] { element }).ToList()
                            .SelectMany(element => element).ToList();
                                    

  1. Trim(): Removes any spaces 在开头或结尾。

  2. Split('"'):Split the string 转换成以双引号作为分隔符的字符串数组

  3. Select()Only select a specific part from the element 正在迭代。在这种情况下,它的元素及其在整个字符串中的索引(从 0 开始)。

  4. 在您的 select 语句中,您有 %2 ==0 .. 这仅适用于其他所有元素。 (跳过 1)

  5. You can do an if else statement?:

    一个。 If true print 1 else print 0 可以认为是true ? print 1 : print 0

  6. SelectMany():返回的Selects all the elements。它不是返回 3 个数组,而是返回每个数组的元素。

  7. ToList(): Converts the array 到一个列表。

【讨论】:

    【解决方案3】:

    似乎这里已经有一些非常好的答案,但是当我看到人们击败我时,我已经快完成我的答案了,所以这是我的版本。希望它能带来一些东西。
    我的方法是用 cmets 用非 Linq 代码写出来

    var line = $"13351.750815 26646.150876 6208.767863 26646.150876 1219.200000 914.400000 0.000000 1 \"Beam 1\" 0 1 1 1 0 1 1e8f59dd-142d-4a4d-81ff-f60f93f674b3";
    line = line.Trim(); //remove leading and trailing white space
    var tempArray1 = line.Split('"'); //split the line to a string array on "
                                      //so the string array we get, is everything before, between, and after "
    
    //.Select((element, index)
    //Basically doing a for-loop on the array we got
    List<string[]> tempListForElements = new List<string[]>(); //initialize a temporary list of string arrays we're going to be using
    for (var index = 0; index < tempArray1.Length; index++)
    {
        var element = tempArray1[index];
    
        //now we're getting to the ternary, which is basically like an inline if-else statement
        //index % 2 == 0 ? <if true> : <if false>
        //if remainder of division by 2 is 0, so basically a way of doing two 
        //different things for every other iterator of the loop
        if (index % 2 == 0)
        {
            //if on the first or last iteraton on the loop (before and after " in the line)
            tempListForElements.Add(element.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries));  //we create yet another string array splitting on each whitespace and add it to our temporary list
        }
        else
        {
            //if on the second iteraton on the loop (between ")
            tempListForElements.Add(new string[] { element }); //we're creating yet another string array, this time there's just one element in the array though, and then add it to our temporary list
        }
    }
    
    //.SelectMany(element => element).ToList()
    //we're basically turning out list of 3 string array into one string array
    //can't be asked to type it out in non linq since just realized there are some good answers here already,
    //but imagine initializing a string array with the correct size and then a foreach loop adding each string to it in order.
    

    【讨论】:

      【解决方案4】:

      如果您在正常的 for 循环中转换此 Linq,它将如下所示。

      var line = $"13351.750815 26646.150876 6208.767863 26646.150876 1219.200000 914.400000 0.000000 1 \"Beam 1\" 0 1 1 1 0 1 1e8f59dd-142d-4a4d-81ff-f60f93f674b3";
          string[] splitLineResult = line.Trim().Split('"');
          var list = new List<string[]>();
          for (int i = 0; i < splitLineResult.Length; i++)
          {
              if (i % 2 == 0) 
              {
                  list.Add(splitLineResult[i].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
              }
              else 
              {
                  list.Add(new string[] { splitLineResult[i] });
              }
          }
          var finalList = list.SelectMany(x=>x).ToList();
      

      对于 SelectMany 方法,您可以参考 MS 文档https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.selectmany?view=netframework-4.8

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-12
        • 2016-09-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多