I have a list of strings:
{"foo", "str1", "str2", ..., "bar", ..., "baz", ...}
I need to get sublists of strings between "foo"
, "bar"
and "baz"
.
Is it possible to do this with linq?
EDIT
I need a method without looking trough the list twice.
You can do this to fine all elements between any two other elements:
var strings = new[] { "foo", "str1", "str2", ... "bar", ... "baz" };
var between = strings.SkipWhile(s => s != "foo").Skip(1)
.TakeWhile(s => s != "bar"); // "str1", "str2", ...
If you want to get everything between "foo" and "baz", except "bar", use this (assuming the order "foo", "bar", "baz"):
var strings = new[] { "foo", "str1", "str2", ... "bar", ... "baz" };
var between = strings.SkipWhile(s => s != "foo").Skip(1)
.TakeWhile(s => s != "baz")
.Where(s => s != "bar"); // "str1", "str2", ...
Or if your comfortable with using Linq queries with side effects, you can do this to partition your input list by certain 'stop' words:
var stops = new[] { "foo", "bar", "baz" };
var strings = new[] { "foo", "str1", "str2", "bar", "str3", "baz" };
var p = -1;
var partitions =
from s in strings
let i = Array.IndexOf(stops, s)
group s by p = i == -1 ? p : i into g
where g.Key == 0 || g.Key == 1
select g.Skip(1); // { "str1", "str2" }, { "str3" }
Or slightly more efficient (since it stops processing after the third stop word):
var partitions =
(from s in strings
let i = Array.IndexOf(stops, s)
group s by p = i == -1 ? p : i)
.SkipWhile(g => g.Key < 0)
.Take(2)
.Select(g => g.Skip(1)); // { "str1", "str2" }, { "str3" }
Now, this method is a little bit rough around the edges, and it's somewhat fiddly when it comes to items before "foo" or after "baz", but if since you're only looking for items between "foo" and "baz", it should work for you. It has the added benefit that the order of the stop words does not affect the results.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With