I have 2 lists of type List<Course>
List<Course> courseTakenFilterListByStatus
List<Course> TakenCoursesNotApplied
I want to find if courseTakenFilterListByStatus.Id is present in the TakenCoursesNotApplied list. Then I need to update Boolean property IsRequired to TRUE. If the value will not be there the property should be set to False.
I don't understand what it has to do with linq.
couldn't you just do the following:
foreach (Course course in courseTakenFilterListByStatus){
// Possibility 1
course.IsRequired = TakenCoursesNotApplied.Contains(course);
// Possibility 2
course.IsRequired = TakenCoursesNotApplied.Any(c => c.Id == course.Id);
}
Don't know if i understodd the logic right. Possibly you have to negate the assigment.
HTH Tobi
Related
How do I check if a Guid value is inside a LIST of Structures?
public struct Info
{
public Guid EntityTypeID;
public String Name;
}
List<Info> InfoList = <function which populates the list of Struct>
...
var values = ctx.EntityValues.Where(v => v.EntityID == e.ID
&& InfoList.Contains(v.EntityTypeItemID)).ToList(); <=== problem here!
//or something like: InfoList[i].EntityTypeID.Contains(v.EntityTypeItemID)).ToList();
Thank you
I suspect you're looking for Any:
... InfoList.Any(x => x.EntityTypeID == v.EntityTypeItemID)
You can't use Contains, because you're looking for something which matches part of the item.
(I'd also strongly discourage using public fields and indeed having mutable structures at all, but that's a different matter.)
Another option would be to create a list of the GUIDs you're interested in:
var guids = InfoList.Select(x => x.EntityTypeID).ToList();
Then you can use:
... guids.Contains(v.EntityTypeItemID)
That may work where the previous code didn't, as it moves the extraction of the type ID out of the main query.
I have a very basic sql view which joins 3 tables: users, pictures, and tags.
How would one create the query below in a way that it won't list the same pictures more than once? In other words, I want to Group By pictures (I think) and return get the first insance of each.
I think this is very similar to the post Linq Query Group By and Selecting First Items, but I cannot figure out how to apply it in this case where the query is instantiating MyImageClass.
validPicSummaries = (from x in db.PicsTagsUsers
where x.enabled == 1
select new MyImageClass {
PicName = x.picname,
Username= x.Username,
Tag = x.tag }).Take(50);
To exclude duplicates, you can use the Distinct LINQ method:
validPicSummaries =
(from x in db.PicsTagsUsers
where x.tag == searchterm && x.enabled == 1
select new MyImageClass
{
PicName = x.picname,
Username= x.Username,
Tag = x.tag
})
.Distinct()
.Take(50);
You will need to make sure that the objects are comparable so that two MyImageClass objects that have the same PicName, Username, and Tag are considered equal (or however you wish to consider two of them as being equal).
You can write a small class that implements IEqualityComparer<T> if you would like to have a custom comparer for just this case. Ex:
private class MyImageClassComparer : IEqualityComparer<MyImageClass>
{
public bool Equals(MyImageClass pMyImage1, MyImageClass pMyImage2)
{
// some test of the two objects to determine
// whether they should be considered equal
return pMyImage1.PicName == pMyImage2.PicName
&& pMyImage1.Username == pMyImage2.Username
&& pMyImage1.Tag == pMyImage2.Tag;
}
public int GetHashCode(MyImageClass pMyImageClass)
{
// the GetHashCode function seems to be what is used by LINQ
// to determine equality. from examples, it seems the way
// to combine hashcodes is to XOR them:
return pMyImageClass.PicName.GetHashCode()
^ pMyImageClass.UserName.GetHashCode()
^ pMyImageClass.Tag.GetHashCode();
}
}
Then when you call distinct:
...
.Distinct(new MyImageClassComparer())
.Take(50);
I am trying to access a user object in a collection with the id = to users101 and set this to another users.
Controller.MyObject.SingleOrDefault(x => x.Id == "user101") = OtherUser();
Thanks in advance.
You can't do it with one LINQ expression.
Usually LINQ extensions works on enumerables, if MyObject is a collection you first have to find the required item and then overwrite it with the new object (moreover SingleOrDefault() will simply return null if condition is not satisfied).
You should write something like this (exact code depends on what MyObject is):
var item = Controller.MyObject.SingleOrDefault(x => x.Id == "user101");
if (item != null)
Controller.MyObject[Controller.MyObject.IndexOf(item)] = new OtherUser();
Please note that if you do not really need the check performed by SingleOrDefault() you can simplify the code (and avoid the double search performed in SingleOrDefault() and IndexOf()).
If this is "performance critical" maybe it is better to write an ad-hoc implementation that does this task in one single pass.
Try it in two lines:
var objectWithId = Controller.MyObject.SingleOrDefault(x => x.Id == "user101");
(objectWithId as WhateverTypeOfObjectOtherUserIs) = OtherUser();
After a lot of searching I wasn't able to find anything that clearly describes why I'm seeing this behavior (and I presume it's something very simple I'm missing - I'm still very much a beginner :)
I have a method (RefreshFilter) that takes an object (rfp) as a parameter. rfp has a property named 'Items' that is of type List.
I have 2 calls to RefreshFilter that look like this:
rfp = RefreshFilter(rfp, FilteredBy.Category)
rfp = RefreshFilter(rfp, FilteredBy.Industry)
Here is the RefreshFilter method:
public FilterParams RefreshFilterList(FilterParams rfp, FilteredBy filteredBy)
{
using (myEntity context as new myEntity())
{
itemsInCategory = (from i in context.items
join ic in context.ItemsCategories on i.Id equals ic.items.id
where ic.Categories.Id == '52'
select i).ToList<items>();
rfp.Items = rfp.Items.Intersect(itemsInCategory).ToList<items>();
}
return rfp;
}
The first call to RefreshFilter(...) works just fine and returns a FilterParams object with a .items property that contains an intersected list.
The second call to RefreshFilter(...) always returns a FilterParams object with a .items property containing an list of 0 elements (which is not expected since I know there are matching elements in the lists).
Through some testing, I believe I have been able to narrow this down to being related to the context that rfp.Items is set in. However I was always under the impression that the proper way to share collections between contexts was to select them into collection objects and pass these objects around, but it seems that these objects are still tied to their initial context in some way.
Thanks,
Try this:
public FilterParams RefreshFilterList(FilterParams rfp, FilteredBy filteredBy)
{
using (myEntity context as new myEntity())
{
itemIdsInCategory = (from i in context.items
join ic in context.ItemsCategories on i.Id equals ic.items.id
where ic.Categories.Id == '52'
select i.Id).ToList<int>();
rfp.Items = rfp.Items.Where(i => itemIdsInCategory.Contains(i.Id)).ToList<Item>();
}
return rfp;
}
Here we are only comparing the unique Ids of the items (int in this case) which could provide a performance benefit as well.
Hello – I’m trying to get a where condition to apply to a sub collection. I can get the criteria to return the proper parents. However, I want the sub collection to be limited to the criteria as well.
In my example code, I only want people with “LINK” skills; also, I only want the skills for each person to equal “LINK.” That is, each person should only have “LINK” for their skills.
Thanks in advance.
List<Skill> skills = new List<Skill>();
skills.Add(new Skill(){SkillName="ASP.NET"});
skills.Add(new Skill(){SkillName="C#"});
Person p1 = new Person(){ Name="Me", Skills=skills} ;
List<Skill> skills2 = new List<Skill>();
skills2.Add(new Skill(){SkillName="ASP.NET"});
skills2.Add(new Skill(){SkillName="C#"});
skills2.Add(new Skill(){SkillName="LINQ"});
Person p2 = new Person(){ Name="You", Skills=skills2} ;
List<Person> People = new List<Person>();
People.Add(p1);
People.Add(p2);
var oResult = (from item in People
from sk in item.Skills
where sk.SkillName == "LINQ"
select item
).ToList();
When I run this. I get p2 (correct), but I want the skills of P2 to only equal LINQ
Do this:
var oResult = (from item in People
where item.Skills.Count() == 1 &&
item.Skills.Any(s => s.SkillName == "LINQ")
select item
).ToList();
This query will return nothing because p2 (You) has other skills in addition to LINQ.
You can do what you want this way:
foreach (var person in oResult)
{
person.Skills.RemoveAll(s => !s.SkillName.Equals("LINQ"));
}
Note: while using LINQ you're only filtering your data. To post process it you use something like the foreach I show you above.
Try this:
var oResult = (from item in People
where item.Skills != null
where item.Skills.Count() > 0
where item.Skills.All(s => s.SkillName == "LINQ")
select item
).ToList();
Even though your example shows that the Skills collection has a value, you want to make sure that your code doesn't blow up if the Skills property is null.
Also, the All predicate returns true if your list is empty so you need to ensure that it is not empty. The above query reads better, but depending on the implementation of the Skills property calling Count() may cause the entire collection to be iterated. You could use Any() instead to ensure that the collection is not empty.
var oResult = (from item in People
where item.Skills != null
where item.Skills.Any()
where item.Skills.All(s => s.SkillName == "LINQ")
select item
).ToList();