【问题标题】:Linq: How to get second lastLinq:如何获得倒数第二
【发布时间】:2012-01-04 08:52:05
【问题描述】:

所以我有一个如下所示的字符串列表:

var ls=new List<string>()
    {
        "100",
        "101-102-1002",
        "105-153-1532-1532",
        "105-1854-45-198",
        "180-95-45-200"
    };

我想得到拆分字符串的倒数第二个。所以我的输出看起来像这样:

null,
102,
1532,
45,
45

我有一个看起来像这样的解决方案:

ls.Select (l =>l.Split('-').Select ((s,i) =>new {s,i})
.OrderByDescending (x=>x.i).Skip(1).Take(1))

我认为这个解决方案对于这个简单的任务可能会很复杂。所以我的问题是:你们有没有一个更简单的解决方案来解决这个问题?

【问题讨论】:

  • 结果错误或者我没有得到问题:不应该是:null,102,153,1235?
  • 你的解决方案对我来说很好!
  • 是的,它应该是拆分字符串的倒数第二个。如果没有倒数第二个,那么它应该返回 null。

标签: c# linq linq-to-sql


【解决方案1】:

Reverse 很适合这里:

ls.SelectMany(l =>l.Split('-').Reverse().Skip(1).Take(1).DefaultIfEmpty())

我还使用SelectManyIEnumerable&lt;IEnumerable&lt;string&gt;&gt; 转换为&lt;IEnumerable&lt;string&gt;

【讨论】:

  • 此解决方案的唯一问题是,当拆分数组长度小于 2 时,您不会得到 'null'。这更接近但不正确,因为这会吐出 Blank 而不是 'null' ls.Select (x => x.Split('-').Reverse().Skip(1).Take(1).FirstOrDefault()).ToList();
  • @Anand 是的,感谢您的提示。但是,我更喜欢我的 LINQ 代码留在 LINQ monad 中。
  • @TimSchmelter 我不明白你。如果ls 为空,则结果将为空。如果ls 中的某个项目太短并且没有至少2 个组件,那么结果将包含null 来代替该项目。这种行为可能看起来很奇怪,但这正是作者想要的,不是吗?
【解决方案2】:
        var ls = new List<string>() { "100", "101-102-1002", "105-153-1532-1532", "12-1235-785" };
        var result = from p in ls
                     let arr = p.Split('-')
                     select arr.Length < 2 ? null : arr[arr.Length - 2];

        foreach (var item in result)
        {
            Console.WriteLine(item);
        }



        Console.Read();

【讨论】:

  • 这应该是答案。它比另一个更快。
【解决方案3】:

如果你有

var ls = new List&lt;string&gt;( ... );

然后

var result = ls.Reverse().Skip(1).Take(1);

应该可以。

【讨论】:

    【解决方案4】:
    var ls = new List<string>(){"100","101-102-1002","105-153-1532-1532","12-1235-785"}; 
    
    var result = from l in ls
                 let s = l.Split('-')
                 select s.ElementAtOrDefault(s.Length - 2);
    

    【讨论】:

    • 当长度小于 2 时不吐出 'null' 而 FirstOrDefault 吐出空白。
    • @Anand,不知道你的意思,它确实为第一个条目返回 null
    【解决方案5】:

      我根据上面 Pavel Gatilov 的回答创建了一个扩展

    public static TSource SecondLast<TSource>(this IEnumerable<TSource> source)
    {
          //from http://stackoverflow.com/questions/8724179/linq-how-to-get-second-last
          return source.Reverse().Skip(1).Take(1).FirstOrDefault();
    }
    

    【讨论】:

      【解决方案6】:
      var ls = new List<string> { "100", "101-102-1002", "105-153-1532-1532", "12-1235-785" };
      var result = ls.Select(x =>
      {
          var tokens = x.Split('-');
          if (tokens.Length < 2)
          {
              return null;
          }
          return tokens[tokens.Length - 2];
      });
      

      【讨论】:

        【解决方案7】:

        在 lambda 语法中:

        var ls = new List<string>() { "100", "101-102-1002", "105-153-1532-1532", "12-1235-785" };
        
        var result = ls.Select(x => new { split = x.Split('-') }).Select(y => y.split.LastOrDefault(z => z != y.split.LastOrDefault()));
        

        【讨论】:

        • 所以您知道,如果您突出显示您的文本并点击“代码”按钮,它将正确格式化它以显示为您的代码块。这次我已经提交并编辑了它。
        【解决方案8】:

        我以某种方式管理了这个页面。 Linq 的答案都不起作用。使用 FirstOrDefault 时,您必须指定 DefaultIfEmpty 并用一个值填充它。如果在运行时需要默认值,它自己的 FirstOrDefault 会中断。接受的答案具有 DefaultIfEmpty 但未指定值。不行,下面的例子就行了。

        var result = ls.DefaultIfEmpty(string.Empty).Reverse().Skip(1).Take(1).FirstOrDefault();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-05-04
          • 1970-01-01
          • 2021-01-06
          • 2019-09-21
          • 2020-11-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多