1

I have two lists of objects, each object has the property Recommendations which itself is a list of 'Recommendation' objects. I want to sort the recommendation objects based on one of its properties. I have come up with this:

TPSqlORs.Where(x => x.Recommendations != null)
    .ToList()
    .ForEach(y => y.Recommendations.OrderBy(z => z.PointNumber));
SbmReportsORs.Where(x => x.Recommendations != null)
    .ToList()
    .ForEach(y => y.Recommendations.OrderBy(z => z.PointNumber));

But it causes no change at all to the original lists, which makes me suspect the ToList() is just making a copy and the sorting is happening on a copy which gets lost after execution. I searched along these lines but apparently whilst it does make a copy, the new list contains references to the original list elements, so surely it should be sorting them for both lists?

3
  • 1
    Please break your habit always to use ToList().ForEach. The ToList creates a fresh new collection from the first, so you are wasting cpu-cycles and even more memory just to be able to use List.ForEach instead of foreach. In this case you're even using it more superfluously since you can chain OrderBy directly behind Where. Commented Oct 2, 2013 at 9:08
  • Exactly what type is Recommendations? Commented Oct 2, 2013 at 9:08
  • @MatthewWatson List<Recommendation> Commented Oct 2, 2013 at 9:09

4 Answers 4

4

OrderBy is not changing order of list. If you want changing order you should write:

y.Recommendations = y.Recommendations.OrderBy(z => z.PointNumber).ToList()

Read about OrderBy

Sign up to request clarification or add additional context in comments.

3 Comments

You'd probably want a ToList call as well - to avoid re-ordering every time it's accessed, apart from anything else.
Should this be within the ForEach? If I replace as you've described I am told y does not exist in the context.
@deed02392 replace your y.Recommendations.OrderBy(z => z.PointNumber) with line above
2

Since Recommendations is in fact a List<Recommendation> you can sort it in-place using List.Sort():

item.Recommendations.Sort((lhs, rhs) => lhs.PointNumber.CompareTo(rhs.PointNumber));

This assumes that item is the object which contains the Recommendations that you want to sort.

If Recommendation elements in the list can be null, you can handle it like this:

item.Recommendations.Sort
(
    (lhs, rhs) =>
    (lhs == null || rhs == null)
    ? Comparer<object>.Default.Compare(lhs, rhs) 
    : lhs.PointNumber.CompareTo(rhs.PointNumber)
);

See List.Sort(Comparison<T> comparison) for details.

Note that List.Sort() is an unstable sort, while Enumerable.OrderBy() is a stable sort, but this is unlikely to make a difference to your case. You need to be aware of the difference though.

[Edit: I have incorporated the code from Jeppe Stig Nielsen's comment below; my thanks to him.]

3 Comments

Can you illustrate how this would best be done from your experience when item is within a List<item> and some of those items may have no Recommendations (null)
@deed02392 Do you mean the Recommendation itself can be null? Then you could do something like (lhs, rhs) => lhs == null || rhs == null ? Comparer<object>.Default.Compare(lhs, rhs) : lhs.PointNumber.CompareTo(rhs.PointNumber). I assume that PointNumber is a non-nullable value type?
Correct @JeppeStigNielsen, thanks for this update. This answer is clearer IMO.
2

OrderBy will never change the order of the original list. It, along with the other LINQ methods, are pure functions. They don't modify the inputs and only create new outputs.

Comments

0

Most of the LINQ expressions don't do changes to the source, they return a resulting collection.

1 Comment

Here it's IOrderedEnumerable

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.