如何根据订购排序

可以说我有物品

items : [{id:1,...}, {id:2,...}, {id:3,...}] 

命令:[ 2,3,1 ]得到一个可枚举的

 items : [{id:2,...}, {id:3,...}, {id:1,...}] 

我希望它能成为符合标准的东西

 items.Select(o => new {key = ordering[i++], value = o}) .OrderBy(k => k.key) .Select(o => o.value) 

但有更清洁的解决方案吗?


我已经validation了这项工作(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,这是用于validation测试:

  [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(); } 

我猜是这样的:

 var result = ordering.Select(x => items.First(y => y.id == x.id)); 

工作范例:

 var items = new[] { new { id = 1, name = "1" }, new { id = 2, name = "2" }, new { id = 3, name = "3" }, new { id = 4, name = "4" } }; var result = new[] { 2, 3, 1 }.Select(x => items.First(y => y.id == x)); 

这也会过滤掉那些items ,其索引不包含在ordering

如果您的ID是连续的,您可以重新排列订单数组以包含每个索引 – 结果数组中具有相同索引的ID的位置。 这可以这样做:

 int[] order = new[] {2, 3, 1}; order = Enumerable.Range(1, order.Length) .OrderBy(x => order[x - 1]) .ToArray(); //Now order = { 3, 1, 2 } which are the one-based indices of each position in the original order array. 

现在您可以使用该结果数组来订购Enumerable

 items = items.OrderBy(x => order[x.Id - 1]); 

请注意,如果您首先以这种方式表示您的订单数组,那么第一个Linq将是不必要的,这样您就没有多余的迭代或子Linq

 int[] order = new[] {3, 1, 2}; //1 is third, 2 is first, 3 is second. items = items.OrderBy(x => order[x.Id - 1]); 

您可以使用Select的重载来代替索引

 items.Select((o,i) => new {key = ordering[i+1], value = o}) .OrderBy(k => k.key) .Select(o => o.value); 

这将更好,因为它消除了示例中捕获的i变量。

如果orderingList ,您可以这样做:

 items.OrderBy(item => ordering.FindIndex(i => i == item.id)) 

唯一的改进是它不需要再次订购或新对象,但基本上与原始代码相同。

 var query = from o in ordering join i in items on o equals i.Id select i;