Страницы

Поиск по вопросам

среда, 5 июня 2019 г.

Как возвратить несколько списков элементов, находящихся, в исходном списке, между двумя ключами, повторяющимися n раз?

Добрый вечер! Пусть есть список List, содержащий KeyValuePair, такой что:
List> _List = new List>() { new KeyValuePair("IGNORKEY1", "IGNORVALUE1"), new KeyValuePair("IGNORKEY1", "IGNORVALUE2"), new KeyValuePair("IGNORKEY1", "IGNORVALUE3"), new KeyValuePair("TRIGGERKEY", "TRIGGERVALUE"), new KeyValuePair("KEY1", "VALUE1"), new KeyValuePair("KEY2", "VALUE2"), new KeyValuePair("KEY2", "VALUE2"), new KeyValuePair("TRIGGERKEY", "TRIGGERVALUE"), new KeyValuePair("KEY3", "VALUE3"), new KeyValuePair("KEY3", "VALUE4"), new KeyValuePair("KEY4", "VALUE5"), new KeyValuePair("TRIGGERKEY", "TRIGGERVALUE"), new KeyValuePair("KEY5", "VALUE6"), new KeyValuePair("KEY6", "VALUE7"), //... };
Значений в _List довольно много.
Только в начале списка есть значения >2 до первой пары ("TRIGGERKEY", "TRIGGERVALUE"), которые нужно игнорировать.
Пара ("TRIGGERKEY", "TRIGGERVALUE") всегда находится перед обычной группой значений.
Между двумя соседними парами ("TRIGGERKEY", "TRIGGERVALUE") всегда есть >2 значений.
Собственно, вопрос в том, какое хорошее решение можно подобрать, для извлечения списка пар, начиная от пары ("TRIGGERKEY", "TRIGGERVALUE"), и до следующей пары ("TRIGGERKEY", "TRIGGERVALUE"), либо конца списка?
Я использовал грубо цикл, успешно, пытался применить linq выражения, но безуспешно.
Заранее огромное спасибо!


Ответ

var trimmed = _List.SkipWhile(el => !(el.Key == "TRIGGERKEY" && el.Value == "TRIGGERVALUE")); int groupIndex = 0;
var groups = trimmed.GroupBy(el => { if (el.Key == "TRIGGERKEY" && el.Value == "TRIGGERVALUE") { groupIndex++; } return groupIndex; });
var result = groups.Select(g => g.Skip(1).ToList()).ToList();
но в этом решение целиком опирается на особенности текущей реализации GroupBy. Поэтому просто цикл - лучше.
Если задача встречается часто, и не хочется копипастить цикл, то лучше написать метод расширения вида
public static class ListExtensions { public static IEnumerable> SplitBy(this IEnumerable source, Func shouldSplit) { List chunk = new List();
foreach (T item in source) { if (shouldSplit(item)) { yield return chunk; chunk = new List(); } else { chunk.Add(item); } }
if (chunk.Count > 0) { yield return chunk; } } }
и вызывать его повсюду как
var result2 = _List.SplitBy(el => el.Key == "TRIGGERKEY" && el.Value == "TRIGGERVALUE") .Skip(1).ToList();

Комментариев нет:

Отправить комментарий