System.Linq.Dynamic.Core icon indicating copy to clipboard operation
System.Linq.Dynamic.Core copied to clipboard

[Question] Many in many predicate

Open AndrzejKl opened this issue 2 years ago • 1 comments

1. Description

I'm trying to filter persons base on filter IEnumerable, but it's not working. What I'm doing wrong?

2. Exception

None

3. Fiddle or Project

https://dotnetfiddle.net/wyYnIQ

code:

using System.Linq.Dynamic.Core;

IList<string> filter = new List<string>() { "b", "c" };

var persons = new List<Person>()
{
    new Person{Name = "asd", Tags = new List<string>() {"b", "d", "e"}},
    new Person{Name = "zxc", Tags = new List<string>() {"g", "a", "e"}},
    new Person{Name = "qwe", Tags = new List<string>() {"a", "c", "e"}},
    new Person{Name = "cvb", Tags = new List<string>() {"z", "f", "k"}},
    new Person{Name = "fgh", Tags = new List<string>() {"w", "x", "q"}},
}.AsQueryable();

var tags = new Tag[]
{
    new Tag(1,"b"),
    new Tag(2, "d"),
    new Tag(3, "e"),
    new Tag(4, "g"),
    new Tag(5, "a"),
    new Tag(6, "c"),
    new Tag(7, "z"),
    new Tag(8, "f"),
    new Tag(9, "k"),
    new Tag(10, "w"),
    new Tag(11, "x"),
    new Tag(12, "q")
};

var personsCompact = new List<PersonCompact>()
{
    new PersonCompact{Name = "asd", Tags = new List<Tag>() { tags[0], tags[1], tags[2] } },
    new PersonCompact{Name = "zxc", Tags = new List<Tag>() { tags[3], tags[4], tags[2]} },
    new PersonCompact{Name = "qwe", Tags = new List<Tag>() { tags[4], tags[5], tags[2]} },
    new PersonCompact{Name = "cvb", Tags = new List<Tag>() { tags[6], tags[7], tags[8]} },
    new PersonCompact{Name = "fgh", Tags = new List<Tag>() { tags[9], tags[10], tags[11]} },
}.AsQueryable();

var outputExpected = persons.Where(u => filter.Any(r => u.Tags.Any(p => p.Equals(r)))).ToList();
var output = persons.Where("Tags.Any((@0).Any())", filter).ToList(); //How to do it?

Console.WriteLine($"Source ({persons.Count()}): " + Environment.NewLine + string.Join(Environment.NewLine, persons) + Environment.NewLine);
Console.WriteLine($"Filter({filter.Count}): " + string.Join(", ", filter) + Environment.NewLine);

Console.WriteLine($"Result Expected({outputExpected.Count}): " + Environment.NewLine + string.Join(Environment.NewLine, outputExpected));
Console.WriteLine($"Result ({output.Count}): " + Environment.NewLine + string.Join(Environment.NewLine, output));

Console.WriteLine(Environment.NewLine);

var outputCompactExpected = personsCompact.Where(u => filter.Any(r => u.Tags.Any(p => p.Name.Equals(r)))).ToList();
var outputCompact = personsCompact.Where("Tags.Any(Name.Equals((@0).Any()))", filter).ToList(); //How to do it?

Console.WriteLine($"Result Tags collection Expected ({outputCompactExpected.Count}): " + Environment.NewLine + string.Join(Environment.NewLine, outputCompactExpected));
Console.WriteLine($"Result Tags collection ({outputCompact.Count}): " + Environment.NewLine + string.Join(Environment.NewLine, outputCompact));

public class Person
{
    public override string ToString() => $"Name: {Name}, Tags: {string.Join("; ", Tags)}";

    public string Name { get; set; }
    public IList<string> Tags { get; set; }
}

public class PersonCompact
{
    public override string ToString() => $"Name: {Name}, Tags: {string.Join("; ", Tags.Select(c => c.Name))}";

    public string Name { get; set; }
    public IList<Tag> Tags { get; set; }
}

public class Tag
{
    public Tag(int id, string name)
    {
        Id = id;
        Name = name;
    }

    public int Id { get; set; }
    public string Name { get; set; }
}

AndrzejKl avatar May 17 '23 08:05 AndrzejKl

I think I got it, can someone confirm it's correct?

var outputExpected = persons.Where(u => filter.Any(r => u.Tags.Any(p => p.Equals(r)))).ToList();
var output = persons.Where("Tags.Any(it in @0)", filter).ToList(); //Correct?

var outputCompactExpected = personsCompact.Where(u => filter.Any(r => u.Tags.Any(p => p.Name.Equals(r)))).ToList();
var outputCompact = personsCompact.Where("Tags.Any(Name in @0)", filter).ToList(); //Correct?

AndrzejKl avatar May 17 '23 08:05 AndrzejKl