Reputation: 2804
public class LogItemTag
{
public int ID { get; set; }
public string Tagname { get; set; }
}
var logItemTags = new List<LogItemTag>();
logItemTags.Add(new LogItemTag { ID = 1, TagName = "red" });
logItemTags.Add(new LogItemTag { ID = 1, TagName = "green" });
logItemTags.Add(new LogItemTag { ID = 3, TagName = "blue" });
logItemTags.Add(new LogItemTag { ID = 3, TagName = "red" });
logItemTags.Add(new LogItemTag { ID = 4, TagName = "green" });
logItemTags.Add(new LogItemTag { ID = 6, TagName = "white" });
logItemTags.Add(new LogItemTag { ID = 7, TagName = "red" });
logItemTags.Add(new LogItemTag { ID = 7, TagName = "green" });
var listOfTagsToFilterOn = new List<string> {"red", "green" };
//I need a list of ids 1 and 7 only.
//this query produces 6 ids - 1,1,3,4,7,7
var query = logItemTags.Where(lit => listOfTagsToFilterOn.Contains(lit.TagName)).Select(lit => lit.ID).ToList();
Upvotes: 2
Views: 391
Reputation: 33381
Use Enumerable.Contains extension method
var filterList = new [] {"red", "green"};
var list = new List<LogItemTag>
{
new LogItemTag {ID =1; TagName = "green"},
....
};
var filteredIds = list.Where(i => filterList.Contains(i.TagName)
.Select(f => f.ID).ToList();
UPDATE
List<LogItemTag> logItemTags = new List<LogItemTag>();
logItemTags.Add(new LogItemTag { ID = 1, TagName = "red" });
logItemTags.Add(new LogItemTag { ID = 1, TagName = "green" });
logItemTags.Add(new LogItemTag { ID = 3, TagName = "blue" });
logItemTags.Add(new LogItemTag { ID = 3, TagName = "red" });
logItemTags.Add(new LogItemTag { ID = 4, TagName = "green" });
logItemTags.Add(new LogItemTag { ID = 6, TagName = "white" });
logItemTags.Add(new LogItemTag { ID = 7, TagName = "red" });
logItemTags.Add(new LogItemTag { ID = 7, TagName = "green" });
var listOfTagsToFilterOn = new List<string> {"red", "green" };
var filteredList = logItemTags.Where(l => listOfTagsToFilterOn.Contains(l.TagName))
.GroupBy(l => l.ID,
l => l.TagName,
(k, t) => new {Id = k, Count = t.Distinct().Count()})
.Where(d => d.Count == listOfTagsToFilterOn.Count())
.Select(d => d.Id).ToList();
Here some explanation
First we group the data by ID and generate objects of anonymous type with ID and distinct count of tags. Then filter them to match tag counts to filter tags count. This will work either you have set the same tag to sme ID.
Upvotes: 2
Reputation: 39366
Use Contains
extension method:
var tags=new List<string>(){"red", "green"};// the collection of tags you want to get the ids
var query=LogItemTagList.Where(l=>tags.Contains(l.Tagname)).Select(l=>l.ID);
I think this is what you are trying to achieve:
var query=LogItemTagList.Where(l=>tags.Contains(l.Tagname))
.GroupBy(l=>l.ID)
.Where(g=>g.Count==tags.Count)
.Select(g=>g.Key)
.ToList();
Upvotes: 2
Reputation: 2821
That's how I would do it. Feel free to edit it / optimize it.
var logItemTags = new List<LogItemTag>();
logItemTags.Add(new LogItemTag { ID = 1, TagName = "red" });
logItemTags.Add(new LogItemTag { ID = 1, TagName = "green" });
logItemTags.Add(new LogItemTag { ID = 3, TagName = "blue" });
logItemTags.Add(new LogItemTag { ID = 3, TagName = "red" });
logItemTags.Add(new LogItemTag { ID = 4, TagName = "green" });
logItemTags.Add(new LogItemTag { ID = 6, TagName = "white" });
logItemTags.Add(new LogItemTag { ID = 7, TagName = "red" });
logItemTags.Add(new LogItemTag { ID = 7, TagName = "green" });
var listOfTagsToFilterOn = new List<string> {"red", "green" };
var list = logItemTags.Where(
x => listOfTagsToFilterOn.All(
y => logItemTags.Any(
z => z.ID == x.ID && y.TagName == z.TagName)))
.Select(x => x.ID).Distinct();
Select all ids that passes all filters (where an item has all tagnames)
Upvotes: 1