简体   繁体   English

Linq相交以针对列表过滤多个条件

[英]Linq intersect to filter multiple criteria against list

I'm trying to filter users by department. 我正在尝试按部门筛选用户。 The filter may contain multiple departments, the users may belong to multiple departments (n:m). 筛选器可能包含多个部门,用户可能属于多个部门(n:m)。 I'm fiddling around with LINQ, but can't find the solution. 我在摆弄LINQ,但找不到解决方案。 Following example code uses simplified Tuples just to make it runnable, of course there are some real user objects. 下面的示例代码使用简化的Tuples只是为了使其可运行,当然还有一些实际的用户对象。

Also on CSSharpPad, so you have some runnable code: http://csharppad.com/gist/34be3e2dd121ffc161c4 同样在CSSharpPad上,因此您具有一些可运行的代码: http ://csharppad.com/gist/34be3e2dd121ffc161c4

string Filter = "Dep1"; //can also contain multiple filters
var users = new List<Tuple<string, string>>
{
    Tuple.Create("Meyer", "Dep1"),
    Tuple.Create("Jackson", "Dep2"),
    Tuple.Create("Green", "Dep1;Dep2"),
    Tuple.Create("Brown", "Dep1")
};

//this is the line I can't get to work like I want to
var tuplets = users.Where(u => u.Item2.Intersect(Filter).Any());


if (tuplets.Distinct().ToList().Count > 0)
{
    foreach (var item in tuplets) Console.WriteLine(item.ToString());
}
else
{
    Console.WriteLine("No results");
}

Right now it returns: 现在它返回:

(Meyer, Dep1)
(Jackson, Dep2)
(Green, Dep1;Dep2)
(Brown, Dep1)

What I would want it to return is: Meyer,Green,Brown . 我希望它返回的是: Meyer,Green,Brown If Filter would be set to "Dep1;Dep2" I would want to do an or-comparison and find *Meyer,Jackson,Green,Brown" (as well as distinct, as I don't want Green twice). If Filter would be set to "Dep2" I would only want to have Jackson, Green . I also played around with .Split(';') , but it got me nowhere. 如果Filter将被设置为"Dep1;Dep2"我希望做一个或对比,找到*迈耶,杰克逊,绿,棕”(以及独特的,因为我不希望格林两次),如果, Filter会设置为"Dep2"我只想让杰克逊·格林 ,我也玩过.Split(';') ,但我无处可去。

Am I making sense? 我说得通吗 I have Users with single/multiple departments and want filtering for those departments. 我有具有单个/多个部门的用户,想要为这些部门进行过滤。 In my output I want to have all users from the specified department(s). 在我的输出中,我希望所有来自指定部门的用户。 The LINQ-magic is not so strong on me. LINQ魔术师对我的吸引力不强。

        string[] Filter = {"Dep1","Dep2"}; //Easier if this is an enumerable
        var users = new List<Tuple<string, string>>
        {
            Tuple.Create("Meyer", "Dep1"),
            Tuple.Create("Jackson", "Dep2"),
            Tuple.Create("Green", "Dep1;Dep2"),
            Tuple.Create("Brown", "Dep1")
        };

        //I would use Any/Split/Contains
        var tuplets = users.Where(u => Filter.Any(y=> u.Item2.Split(';').Contains(y)));


        if (tuplets.Distinct().ToList().Count > 0)
        {
            foreach (var item in tuplets) Console.WriteLine(item.ToString());
        }
        else
        {
            Console.WriteLine("No results");
        }

Since string implements IEnumerable , what you're doing right now is an Intersect on a IEnumerable<char> (ie you're checking each letter in the string). 由于string实现了IEnumerable ,所以您现在正在做的是IEnumerable<char>上的Intersect (即,您正在检查字符串中的每个字母)。 You need to split on ; 你需要分裂; both on Item2 and Filter and intersect those. Item2Filter相交。

var tuplets = users.Where(u => 
    u.Item2.Split(new []{';'})
    .Intersect(Filter.Split(new []{';'}))
    .Any());

In addition to the other answers, the Contains extension method may also be a good fit for what you're trying to do if you're matching on a value: 除了其他答案之外,如果您匹配值,则Contains扩展方法也可能非常适合您尝试执行的操作:

var result = list.Where(x => filter.Contains(x.Value));

Otherwise, the Any method will accept a delegate: 否则, Any方法将接受委托:

var result = list.Where(x => filter.Any(y => y.Value == x.Value));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM