如何根据订购排序

时间:2015-12-11 12:31:51

标签: c# .net lambda

让我说我有物品

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)

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

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

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

5 个答案:

答案 0 :(得分:3)

我猜是这样的事情:

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的{​​{1}},其索引不包含在ordering中。

答案 1 :(得分:3)

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

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

这会更好,因为它会删除示例中捕获的i变量。

答案 2 :(得分:3)

如果您的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将是不必要的,这样 您没有多余的迭代或子{{1} }Š

Linq

答案 3 :(得分:2)

如果orderingList,您可以这样做:

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

答案 4 :(得分:2)

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

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