Создать меньшие списки из существующего списка на основе разделителя - PullRequest
0 голосов
/ 04 июля 2019

У меня есть список, который состоит из коллекции небольших списков.Мне нужно разбить этот агрегированный список на меньшие списки на основе определенного значения.

Я пытался использовать метод .Take (), но он принимает целое число, и я не обязательно знаю, как долго будет меньший списокбудет.

Мой список большой список выглядит примерно так

List<T> Foo = new List<T>();
Foo.Add("Test1", "LineTypeA");
Foo.Add("Test2", "LineTypeA");
Foo.Add("Test3", "LineTypeB");
Foo.Add("Test4", "LineTypeA");
Foo.Add("Test5", "LineTypeB");

List<List<T> Bar = new List<ListT>>();
Bar.Add(Foo);

Мне нужно иметь возможность разделить "Бар" на меньшие списки на основе "LineTypeB".Таким образом, один список будет содержать 3 элемента, а другой список будет содержать два из примера выше.В этом потоке есть аналогичное решение, чтобы делать то, что я хочу, но в python - Python, разбивающий список на основе слова разделителя

Ответы [ 2 ]

0 голосов
/ 05 июля 2019

Вот эквивалент C # ответа в вопросе Python. Я изменил его, чтобы не брать разделитель, а вместо этого взять делегат, который определяет, является ли элемент разделителем. Также я исправил это, чтобы не возвращать пустые коллекции, когда коллекция пуста или первый элемент соответствует.

public static IEnumerable<IEnumerable<T>> SplitOn<T>(
    this IEnumerable<T> items, 
    Func<T, bool> split)
{
    var g = new List<T>();
    foreach(var item in items)
    {
        if(split(item) && g.Count > 0)
        {
            yield return g;
            g = new List<T>();
        }

        g.Add(item);
    }

    if(g.Count > 0) yield return g;
}

Тогда вы можете использовать это с вашим примером, как это.

var results = Bar.SelectMany(x => x).SplitOn(x => x.Value == "LineTypeB");
0 голосов
/ 04 июля 2019

Предположим, у вас есть ваш тип, который будет содержать ваш список:

public class MyItem
{
    public string Key { get; set; }

    public string Value { get; set; }

    public MyItem(string key, string value)
    {
        Key = key;
        Value = value;
    }
}

И у вас есть начальные списки, созданные следующим образом:

List<MyItem> Foo1 = new List<MyItem>();
Foo1.Add(new MyItem("Test1", "LineTypeA"));
Foo1.Add(new MyItem("Test2", "LineTypeA"));
Foo1.Add(new MyItem("Test3", "LineTypeB"));
Foo1.Add(new MyItem("Test4", "LineTypeA"));
Foo1.Add(new MyItem("Test5", "LineTypeB"));

List<MyItem> Foo2 = new List<MyItem>();
Foo2.Add(new MyItem("Test1", "LineTypeA"));
Foo2.Add(new MyItem("Test2", "LineTypeA"));
Foo2.Add(new MyItem("Test3", "LineTypeB"));
Foo2.Add(new MyItem("Test4", "LineTypeA"));
Foo2.Add(new MyItem("Test5", "LineTypeB"));

List<MyItem> Foo3 = new List<MyItem>();
Foo3.Add(new MyItem("Test1", "LineTypeA"));
Foo3.Add(new MyItem("Test2", "LineTypeA"));
Foo3.Add(new MyItem("Test3", "LineTypeB"));
Foo3.Add(new MyItem("Test4", "LineTypeA"));
Foo3.Add(new MyItem("Test5", "LineTypeB"));


List<List<MyItem>> Bar = new List<List<MyItem>> ();
Bar.Add(Foo1);
Bar.Add(Foo2);
Bar.Add(Foo3);

Далее, вы можете использовать LINQ для создания плоского списка (возможно, он даже не нужен, если у вас будет только один внутренний список, например, только Foo1):

List<MyItem> flatList = Bar.SelectMany(innerList => innerList).ToList();
string expectedValue = "LineTypeB";

А теперь самое важное, что вы можете сделать, создав метод расширения для списка:

public static class ListExtensionMethods
{
    public static List<List<MyItem>> SplitListByValue(this List<MyItem> list, string value)
    {
        List<List<MyItem>> splittedList = new List<List<MyItem>>() { new List<MyItem>() }; // initial set

        for (int i = 0; i < list.Count; i++)
        {
            var currentItem = list[i];
            if (i == 0 && currentItem.Value == value) //if the first element already meets the condition, add it to the first sublist and create new one
            {
                splittedList.LastOrDefault().Add(currentItem);
                splittedList.Add(new List<MyItem>());
            }
            else if (currentItem.Value == value)
            {
                splittedList.Add(new List<MyItem>()); //if i-th element meets the condition, create new sublist and add it there
                splittedList.LastOrDefault().Add(currentItem);
            }
            else
            {
                splittedList.LastOrDefault().Add(currentItem);
            }
        }

        return splittedList;
    }
}

А потом вы называете это так, как следует из вашего flatList:

var splitList = flatList.SplitListByValue(expectedValue);

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...