Lets say I have items
items : [{id:1,...}, {id:2,...}, {id:3,...}]
and have ordering : [2, 3, 1] to get an enumerable
items : [{id:2,...}, {id:3,...}, {id:1,...}]
I expect it to be something in the lines of
items.Select(o => new {key = ordering[i++], value = o})
.OrderBy(k => k.key)
.Select(o => o.value)
but is there a cleaner solution?
Following I have verified that work (HimBromBeere, Domysee, qxg)
var expectedOrder = ordering.Select(x => result.First(o => o.Id == x));
var expectedOrder = result.OrderBy(item => Array.FindIndex(ordering,i => i == item.Id));
var expectedOrder = result.OrderBy(item => ordering.ToList().FindIndex(i => i == item.Id));
var expectedOrder =
from o in ordering
join i in result
on o equals i.Id
select i;
Fwi, this was for verification test:
[Test]
[TestCase(1, 2, 3)]
[TestCase(1, 3, 2)]
[TestCase(2, 1, 3)]
[TestCase(2, 3, 1)]
[TestCase(3, 1, 2)]
public void Test_Should_Fail_If_GetMessages_Does_Not_Return_Sorted_By_Sent_Then_By_Id_Result(params int[] ordering)
{
var questions = GetQuestionsData();
Mock.Get(_questionService)
.Setup(o => o.GetQuestions())
.Returns(questions);
var result = _mailboxService.GetMessages();
var expectedOrder = ordering.Select(x => result.First(o => o.Id == x));
// Act
Action sortOrder = () => expectedOrder.Should()
.BeInDescendingOrder(o => o.Sent)
.And.BeInDescendingOrder(o => o.Id);
// Assert
sortOrder.ShouldThrow<AssertionException>();
}
Something like this I guess:
Working example:
This also filters those
items
out, whose index is not contained inordering
.The only improvement is that it doesn't need order again or new object, but essentially is the same as original code.
You could use the overload of
Select
that gives you the index insteadThis will be better because it eliminates the captured
i
variable in your example.If
ordering
is aList
, you can do that:If your IDs are consecutive you can rearrange the order array to contain for each index - the position the ID with the same index in the result array. This can be done like that:
Now you can just order your
Enumerable
using that result array:Note that if you would represent your order array this way in first place, the first
Linq
would be unnecessary, and this way you have no redundant iterations or sub-Linq
s: