Reputation: 31239
So i have a List of strings that looks like this:
var ls=new List<string>()
{
"100",
"101-102-1002",
"105-153-1532-1532",
"105-1854-45-198",
"180-95-45-200"
};
I want to get the second last of the the split string. So my output looks like this:
null,
102,
1532,
45,
45
I have a solution for it that looks like this:
ls.Select (l =>l.Split('-').Select ((s,i) =>new {s,i})
.OrderByDescending (x=>x.i).Skip(1).Take(1))
I think that this solution might be to complex for this simple task. So my question is: Do any of you have a simpler solution to this problem?
Upvotes: 43
Views: 34413
Reputation: 89
I somehow managed across this page. None of Linq answers would work. When using FirstOrDefault you have to specify DefaultIfEmpty and populate it with a value. FirstOrDefault on it's own will break if at runtime the default is required. The accepted answer had DefaultIfEmpty but doesn't specify a value. It wouldn't work, the following example will.
var result = ls.DefaultIfEmpty(string.Empty).Reverse().Skip(1).Take(1).FirstOrDefault();
Upvotes: 4
Reputation: 28435
I've created an extension based on Pavel Gatilov's answer above
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();
}
Upvotes: 5
Reputation: 1
In lambda syntax:
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()));
Upvotes: 0
Reputation: 7661
Reverse
fits well here:
ls.SelectMany(l =>l.Split('-').Reverse().Skip(1).Take(1).DefaultIfEmpty())
I also use SelectMany
to transform IEnumerable<IEnumerable<string>>
to <IEnumerable<string>
.
Upvotes: 51
Reputation: 5930
If you have
var ls = new List<string>( ... );
then
var result = ls.Reverse().Skip(1).Take(1);
should work.
Upvotes: 9
Reputation: 57783
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);
Upvotes: 7
Reputation: 4294
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();
Upvotes: 15
Reputation: 1038720
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];
});
Upvotes: 2