说我有一个List<string> listOfStrings,我想根据某些谓词将此列表分为两个列表。例如,第一个列表应包含所有以字母开头的字符串,第二个列表则为不包含字母的列表。
现在,我将这样做:
var firstList = listOfStrings.Where(str => predicate(str));
var secondList = listOfStrings.Where(str => !predicate(str));
Run Code Online (Sandbox Code Playgroud)
有没有一种更好的方法可以做到这一点?
您可以使用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
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 或其他东西可能会更方便。