Divide list in item lists by item

I have a list of lines:

{"foo", "str1", "str2", ..., "bar", ..., "baz", ...} 

I need to get sublist lines between "foo" , "bar" and "baz" .

Can this be done with linq?

EDIT

I need a method without looking at the list twice.

+4
source share
3 answers

You can do this to clear 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 for "bar", use this (assuming the order is "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 it’s convenient for you to use Linq queries with side effects, you can do this to split your input list into specific β€œ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 a little 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 rough around the edges, and it is somewhat inconvenient when it comes to elements before "foo" or after "baz", but if you are only looking for elements between "foo" and "baz", it should work for you. It has the added benefit that stop word order does not affect the results.

+6
source
 var idxFoo = list.IndexOf("foo"); var idxBar = list.IndexOf("bar"); var idxBaz = list.IndexOf("baz"); var subList1 = list.Skip(idxFoo).Take(idxBar - idxFoo); var subList2 = list.Skip(idxBar).Take(idxBaz - idxBar); 
+4
source

If you want to repeat only once in your extensive data list, you can do this:

 List<string> longDataList = new List<string> { "foo", "str1", "str2", "str1", "str2", "str1", "str2", "bar", "str1", "str2", "str1", "str2", "str1", "str2", "baz", "str1", "str2", "str1", "str2", "str1", "str2" }; List<string> splitters = new List<string> { "foo", "bar", "baz" }; Dictionary<string, List<string>> resultDict = new Dictionary<string, List<string>>(); List<string> currentList = null; longDataList.ForEach(s => { if (splitters.Contains(s)) { if (resultDict.ContainsKey(s)) currentList = resultDict[s]; else { currentList = new List<string>(); resultDict.Add(s, currentList); } } else currentList.Add(s); }); 

Uses at least a little linq, but does a trick that repeats only once through your extensive data list.

0
source

Source: https://habr.com/ru/post/1485626/


All Articles