2012-01-04 124 views
20

所以我有一個字符串列表,看起來像這樣:的LINQ:如何獲得倒數第二

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)) 

我認爲這種解決方案可能是複雜,這個簡單的任務。所以我的問題是:你們有沒有更簡單的解決方案來解決這個問題?

+2

分機的結果是錯誤的或者我不明白的問題:應該不會吧be:null,102,153,1235? – 2012-01-04 08:55:36

+1

您的解決方案對我來說看起來很好! – ColinE 2012-01-04 08:55:46

+0

是的,它應該是拆分字符串的第二個最後一個。如果沒有倒數第二個,那麼它應該返回null。 – Arion 2012-01-04 09:00:25

回答

31

Reverse非常適合在這裏:

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

我也用SelectMany改造IEnumerable<IEnumerable<string>><IEnumerable<string>

+1

這種解決方案的唯一的問題是你不會得到「空」時splited陣列長度小於2 這是接近但不正確的,因爲這吐出空白而不是「空」 ls.Select(X => X 。.Split( ' - ')反向()跳過(1)。取(1).FirstOrDefault())ToList(); – Anand 2012-01-04 09:14:19

+0

@Anand是的,謝謝你的提示。不過,我更喜歡我的LINQ代碼留在LINQ monad中。 – 2012-01-04 09:20:46

+0

@TimSchmelter我不明白你的意思。如果'ls'爲空,則結果將爲空。如果'ls'中的項太短而且沒有至少兩個組件,則結果將包含'null'來代替該項。這種行爲可能看起來很奇怪,但這是作者想要的,不是嗎? – 2014-04-24 05:43:49

2
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]; 
}); 
12
 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(); 
+0

這應該是答案。它比另一個更快。 – DanielCuadra 2014-04-09 16:34:31

6
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); 
+0

長度小於2時不吐出'空',而是FirstOrDefault吐出空白。 – Anand 2012-01-04 09:16:13

+0

@Anand,不確定你的意思,它確實爲第一個條目返回'null'。 – 2012-01-04 09:27:10

6

如果你有

var ls = new List<string>(...);

然後

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

應該工作。

0

在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())); 
+0

所以,你知道,如果你突出顯示你的文本並點擊「代碼」按鈕,它將正確格式化爲代碼塊顯示給你。這次我已經提交併提交併編輯了它。 – Amicable 2014-04-09 16:29:08

1

我已經創建了一個基於帕維爾·加季洛夫的回答以上

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(); 
}