C#使用bool函数将列表分为两个列表

edd*_*P23 2 c# list filter

说我有一个List<string> listOfStrings,我想根据某些谓词将此列表分为两个列表。例如,第一个列表应包含所有以字母开头的字符串,第二个列表则为不包含字母的列表。

现在,我将这样做:

var firstList = listOfStrings.Where(str => predicate(str));
var secondList = listOfStrings.Where(str => !predicate(str));
Run Code Online (Sandbox Code Playgroud)

有没有一种更好的方法可以做到这一点?

hai*_*770 7

您可以使用Linq的GroupBy()

var splitted = listOfStrings.GroupBy(s => Char.IsLetter(s[0]));
Run Code Online (Sandbox Code Playgroud)

与您的一起predicate,它将是:

Func<string, bool> predicate;

var splitted = listOfStrings.GroupBy(predicate);
Run Code Online (Sandbox Code Playgroud)

用法:

最简单的方法是将分组数据转换为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];
Run Code Online (Sandbox Code Playgroud)

当然,有很多方法可以将数据整理到所需的结构中,但是在我看来,以上内容非常简洁。

参见MSDN


tho*_*ius 5

Kotlin 有分区函数(来源)。C# 版本:

var (first, second) = list.Partition(x => x.IsTrue);
Run Code Online (Sandbox Code Playgroud)

扩大:

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]);
}
Run Code Online (Sandbox Code Playgroud)

List<T>根据用例,使用 return 或使用 GroupBy 或其他东西可能会更方便。