2

Below is my class:

public class Test
{
    public string Name {get;set;}
    public int  ID {get;set;}
    public IList<string> Tags {get;set;}

    Public Test()
    {
        Tags = new List<string>();
    }
}

Now I have another list called tags which data type is List<string> with some values.

Now I want to write a query:

var results = List<Test>().Where(x=>x.Tags.Contains(tags));

But tags is not allowed inside Contains, since Contains allow only string type.

Actual error is:

Argument 1: cannot convert from 'System.Collections.Generic.IList' to 'string'

May I know how to handle this situation in Lambda.

SomeBody
  • 7,515
  • 2
  • 17
  • 33

3 Answers3

2

I assume you want to get all results where at least one tag is in your second list tags. You can use Intersect to do so:

var results = List().Where(x=>x.Tags.Intersect(tags).Any())
SomeBody
  • 7,515
  • 2
  • 17
  • 33
  • Actually I want to display all results from second list Tags. I used above syntax but i am getting error. – mcp developer Apr 12 '21 at 11:33
  • Server Error in '/' Application. Cannot understand how to translate method 'Intersect' of 'System.Linq.Enumerable' type. – mcp developer Apr 12 '21 at 11:35
  • 2
    @mcpdeveloper That's why it's important to tell the whole story when asking a question. Apparently `List()` is an `IQueryable` from, probably, Entity Framework. So which EF version is this, which database provider, and how is `Test` mapped to the database? Please add this information to your question. – Gert Arnold Apr 12 '21 at 12:12
  • 1
    @mcpdeveloper You did not write that you use any ORM framework. When you ask a question next time, please provide all information necessary to answer the question direcetly. – SomeBody Apr 12 '21 at 12:26
  • Just to add : I am using like below var results = RavenSession.Query().Where(x=>x.Tags.Intersect(tags).Any()). RavenSession.Query is an IRavenQueryable. – mcp developer Apr 15 '21 at 07:36
1

So you give us some code that doesn't do what you want, and you want us to write code that does do what you want.

Wouldn't it be nice if you told us what your want?

I'll try to make a good guess.

So you have a sequence of Tests, where every Test has a property Tags, which is a sequence of strings.

You also have a sequence of Tags, which is also a sequence of strings.

IEnumerable<Test> tests = ...
IEnumerable<string> tags = ...

Which of the following four do you want?

I want only those Tests that have

  • a value for property Tags equal to Tags (same values, same order)
  • exactly the same Tags that are in tags (same values, any order)
  • have at least all Tags that are in sequence of Tags (more values)
  • have only Tags that are in my sequence of Tags (less values)

Tags equal to tags: same value, same order

For this, use one of the overloads of Enumerable.SequenceEqual

var result = tests.Where(test => test.Tags.SequenceEqual(tags));

In words: from all tests, keep only those Tests that have a sequence of strings in property Tags that is exactly the same sequence as we have in tags: same number of strings, in the same order.

If you want, you can use an equality comparer, for instance:

IEqualityComparer<string> tagComparer = StringComparer.OrdinalIgnoreCase;
var result = tests.Where(test => test.Tags.SequenceEqual(tags, tagComparer));

Exactly the same Tags that are in tags: same values, any order

For this it is wise to put your tags in a HashSet<string>, this is a fast method to see if two sequences have the same elements:

HashSet<string> setTags = new HashSet<string>(tags);
var result = tests.Where(test => setTags.SetEquals(test.Tags));

SetEquals returns true if exactly the same elements, in any order, duplicates are ignored.

Or course, you can use an equality comparer:

HashSet<string> setTags = new HashSet<string>(tags, tagComparer);

There is a wee problem here:

tags = new string[] {"1", "1", "1", "1","1", "1", "1", "1"}
Test = new Test
{
    Tags = new string[] {"1", "1"},
    ...
}

Do you want to keep this test? Let's ignore the duplicates.

at least all Tags that are in sequence of Tags: more values

Once you've created the HashSet, the other two are easy

At least all Tags that are in sequence of Tags: more values

var result = tests.Where(test => setTags.IsSuperSetOf(test.Tags));

Only Tags that are in my sequence of Tags: less values

var result = tests.Where(test => setTags.IsSubSetOf(test.Tags));
Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116
0

Another solution as far as I understood:

var results = List().Where(x=> x.Tags.Any(y => tags.Any(z => z == y)));

It is however not optimal and might be slow in case if the tag lists are big and the solution above is better. But it is still a solution.

Samy Sammour
  • 2,298
  • 2
  • 31
  • 66