Nathan
Nathan

Reputation: 979

Sort List based on object properties in another List

I need to find objects common to two lists, based on a different property on the objects in each list (objects in one list have a targetId property, I need to find all objects where the targetId matches the Id of objects in the first list. Objects in both lists have a range of other distinct properties.

The first list will define the order for the matched objects - the actual order doesn't matter, so long as both lists are ordered the same. Example below [pseudocode] shows what I mean, where the second list is sorted by TargetId to match the Id order in the first list:

firstList = [{name: a, id:1}, {name: b, id:2}, {name: c, id:3}]
secondList = [{name: d, targetId: 2}, {name:e, targetId: 3}, {name: f, targetId: 1}]

sortedList = [{name: f, targetId: 1}, {name:d, targetId: 2}, {name: e, targetId: 3}]

I thought something like the below would work, but I'm getting a sequence contains no elements error, even though I know each object has a match in the other list. Have tried sorting in place with no success.

List<object> firstList; // objects have an Id
List<object> secondList; // objects have a TargetId property
List<object> sortedList = new List<object>(); // the new list to store matched objects

foreach (object o in firstList) {
    sortedList.Add(secondList.Where(x => x.TargetId == o.Id).First()); // should only return one object, but First() just in case
}

foreach (object o in sortedList) {
    //do something with the ordered list
}

Upvotes: 0

Views: 2496

Answers (1)

McGarnagle
McGarnagle

Reputation: 102753

I suggest converting the first loop to a Linq statement. The way you have it set up looks vulnerable to a modified closure problem:

var sortedList = firstList.Select(o => 
    secondList.First(x => x.TargetId == o.Id))
.ToList();

I'm not sure where the "sequence contains no elements" error could be coming from other than First() -- are you sure there are no elements in firstList that have no match in secondList? The below would be a good double-check (FirstOrDefault instead of First, with a null check):

var sortedList = firstList.Select(o => 
    secondList.FirstOrDefault(x => x.TargetId == o.Id))
.Where(item => item != null)
.ToList();

Upvotes: 3

Related Questions