How to split a list of strings into other lists if a particular string meets the condition using linq?

I have a list {a,b,c,at,h,c,bt} I like to split List<List<string>>{{a,b,c},{at,h,c},{bt}}; if specific lines contain "t"I need to break this line, how can I do it in linq?

+3
source share
4 answers

Well, there’s a terrible way to do this:

int tCounter = 0;
var groups = sequence.GroupBy(x => x.Contains("t") ? ++tCounter : tCounter)
                     .Select(group => group.ToList())
                     .ToList();

or equivalent (but without calling Select):

int tCounter = 0;
var groups = sequence.GroupBy(x => x.Contains("t") ? ++tCounter : tCounter,
                              (count, group) => group.ToList())
                     .ToList();

It depends on the side effect in the article GroupBy- this is a really bad idea. LINQ is designed around functional ideals where queries should not have side effects. You put side effects in the code that uses the request, and not in the request itself. This will work, but I would not recommend it.

, , , :

using System;
using System.Collections.Generic;
using System.Linq;

public class Test
{
    static void Main(string[] args)
    {
        var input = new List<string>{"a","b","c","at","h","c","bt"};

        int tCounter = 0;
        var groups = input.GroupBy(x => x.Contains("t") ? ++tCounter : tCounter)
                          .Select(group => group.ToList())
                          .ToList();
        foreach (var list in groups)
        {
            Console.WriteLine(string.Join(", ", list));
        }
    }
}

:

a, b, c
at, h, c
bt

"" (, , , ), , . Ts, , GroupBy .

, IIRC - Reactive Extensions System.Interactive assembly . . LINQ.

+4

, , .

var source = new List<string> { "a", "b", "c", "at", "h", "c", "bt" };
var result = source.Aggregate(new List<List<string>>(), (list, s) =>
    {
        if (list.Count == 0 || s.Contains('t')) list.Add(new List<string>());
        list.Last().Add(s);
        return list;
    });

result List<List<string>>.

+2

, Linq (, ... ), :

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, Func<T, bool> isSeparator)
{
    List<T> list = new List<T>();
    foreach(T item in source)
    {
        if (isSeparator(item))
        {
            if (list.Count > 0)
            {
                yield return list;
                list = new List<T>();
            }
        }
        list.Add(item);
    }

    if (list.Count > 0)
    {
        yield return list;
    }
}

:

var list = new[] { "a", "b", "c", "at", "h", "c", "bt" };
var result = list.Split(s => s.Contains("t"));
+1

This problem does not scream LINQ to me. If you request the LINQ answer as a mental exercise, this is something else, but here is how I will resolve it (using a simple old loop):

        List<List<string>> list = new List<List<string>>();
        List<string> sublist = new List<string>();
        foreach (string element in originalList)
        {
            if (element.Contains("t"))
            {
                list.Add(sublist);
                sublist = new List<string>();
            }
            sublist.Add(element);
        }
        list.Add(sublist);

Don't get me wrong, I abuse LINQ more than anyone. :)

0
source

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


All Articles