使用LINQ自定义排序

时间:2009-09-18 10:38:24

标签: c# linq sorting

似乎我错过了一些微不足道的东西。

无论如何,这里是:

var order = new[]{1,3,2};
var foos = new[]{new Foo{Id=1}, new Foo{Id=2}, new Foo{Id=3}};

如何使用Linq按顺序数组对foos进行排序?

期望的结果:

foos == new[]{new Foo{Id=1}, new Foo{Id=3}, new Foo{Id=2}};

修改
订单包含Foo ID。对不起,我没有提到。有时候提问问题比回答问题更难。 :)

6 个答案:

答案 0 :(得分:4)

这是你想要做的吗?

foos.OrderBy(f => order[f.Id-1]);

如果你现在预先输出,打印ID,你会得到:1,3,2

答案 1 :(得分:3)

from o in order.Select((o, i) => new { o, i })
join f in foos on o.o equals f.Id
orderby o.i
select f;

答案 2 :(得分:3)

好的,这个问题对我来说似乎并不完全 >

  • 您有一系列ID,按所需顺序
  • 您有一组对象,的顺序正确,但具有相应的ID
  • 您希望以与ID序列相同的顺序获取对象集合

正确?

那将是:

var orderedFoos = from orderedId in order
                  join foo in foos on orderedId equals foo.Id into groups
                  select groups.Single();

您需要join ... into来验证foos中没有任何丢失或重复的ID。但是,它不会检测您是否在order中丢失或重复了ID。如果您知道所有内容都是正确的(即foos中的每个条目order中只有一个条目,反之亦然),那么简单的加入就可以了:

var orderedFoos = from orderedId in order
                  join foo in foos on orderedId equals foo.Id
                  select foo;

可以用点符号表示为:

var orderedFoos = order.Join(foos, order => order, foo => foo.ID, (o, f) => f);

答案 3 :(得分:1)

如果我有很多要做的话,我可能会使用Dictionary<int,int> id / ordering对来进行订单查找O(1)。请注意,您还需要处理订单中缺少值的情况 - 我选择将它们移到最后。

var order = new Dictionary<int,int>();
order.Add( 1, 1 );
order.Add( 2, 3 );
order.Add( 3, 2 );

var orderedFoos = foos.OrderBy( f => order.Contains(f.Id) ? order[f.Id] : int.MaxValue );

答案 4 :(得分:1)

您可以使用嵌套查询执行此操作,但使用O(n²)效率非常低。

var result = order.Select(o => foos.Single(f => f.Id == o));

如果'order'可能包含'foos'中不存在的ID,则应使用SingleOrDefault()。如果foos可能包含重复的ID,则应使用First()FirstOrDefault()

var result = order
    .Select(o => foos.FirstOrDefault(f => f.Id == o))
    .Select(f => f != null);

甚至连接都可行,但我不确定它是否会保留订单。

var result = Enumerable.Join(order, foos, o => o, f => f.Id, (o, f) => f);

正如Jon所提到的,如果输入的形式与我的第一个建议所需的方式相同,则连接只能正常工作。

答案 5 :(得分:0)

var order = new[] { 1, 3, 2 };
var foos = new[] { new Foo { Id = 1 }, new Foo { Id = 2 }, new Foo { Id = 3 } };

var query = from o in order
            join foo in foos on o equals foo.Id
            select foo;

var foos2 = query.ToArray();