С# разделить список на два списка, используя функцию bool

Скажем, у меня есть List<string> listOfStrings, и я хочу разделить этот список на два списка на основе некоторого предиката. Например, первый список должен содержать все строки, начинающиеся с буквы, а второй — список строк, которые не начинаются.

Теперь я бы сделал это так:

var firstList = listOfStrings.Where(str => predicate(str));
var secondList = listOfStrings.Where(str => !predicate(str));

Есть ли лучший способ сделать это в одну строку?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
518
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Вы можете использовать Linq GroupBy():

var splitted = listOfStrings.GroupBy(s => Char.IsLetter(s[0]));

А с вашим predicate это будет:

Func<string, bool> predicate;

var splitted = listOfStrings.GroupBy(predicate);

Применение:

Самый простой способ — преобразовать сгруппированные данные в Dictionary<bool, IEnumerable<string>>, когда ключ — это bool, обозначающий, начинаются ли элементы в нем с буквы:

var splitted = list.GroupBy(x => Char.IsLetter(x[0]))
                   .ToDictionary(x => x.Key, z => z.ToArray());  

var startWithLetter = splitted[true];
var dontStartWithLetter = splitted[false];

Конечно, есть много способов преобразовать данные в желаемую структуру, но, на мой взгляд, вышеизложенное довольно лаконично.

См. MSDN

Спасибо, но для полноты картины, не могли бы вы добавить пример извлечения обоих списков из splitted?

eddyP23 13.06.2019 10:11

@eddyP23, Готово.

haim770 13.06.2019 10:23

Вы можете использовать «GroupBy» или «ToLookup», в зависимости от того, что вы будете делать с результатами. Проверьте также поиск против группового

Я бы сделал что-то вроде этого:

class Program
{
    static void Main(string[] args)
    {
        Func<string, bool> startsWithA = s => s[0] == 'a';

        List<string> listOfStrings = new List<string>()
        {
            "abc",
            "acb",
            "bac",
            "bca",
            "cab",
            "cba"
        };

        Dictionary<bool, List<string>> dictionaryOfListsOfStrings = listOfStrings.GroupBy(startsWithA).ToDictionary(x => x.Key, x => x.ToList());
    }
}

В Kotlin есть функция раздел (источники). С# версия:

var (first, second) = list.Partition(x => x.IsTrue);

Расширение:

public static (IEnumerable<T> first, IEnumerable<T> second) Partition<T>(this IEnumerable<T> list, Func<T, bool> predicate)
{
    var lookup = list.ToLookup(predicate);
    return (lookup[true], lookup[false]);
}

Может быть удобнее вернуть List<T> или использовать GroupBy или что-то еще, в зависимости от варианта использования.

Другие вопросы по теме