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

时间:2019-06-13 07:59:12

标签: c# list filter

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

现在我要这样做:

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

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

4 个答案:

答案 0 :(得分:7)

您可以使用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

答案 1 :(得分:1)

您可以根据要处理的结果使用“ GroupBy”或“ ToLookup”。 还要检查lookup vs. groupby

答案 2 :(得分:1)

Kotlin 有 partition 函数(如果有兴趣,请参考 here)。它可以在 C# 中看起来像:

var (firstList, secondList) = listOfStrings.Partition(str => predicate(str));

扩展:

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 或其他东西可能更方便,具体取决于用例。

答案 3 :(得分:0)

我会做这样的事情:

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());
    }
}