5

想象一下,您有一个名为 的列表List<Foo>

Foo是一个抽象类,所以它可以是FooA, FooB,FooCFooD. 而且我想要一个扩展List<T>,您可以按类型顺序排列这些元素。

例如,如果我有 9 个元素。

FooA, FooA, FooB, FooD, FooC, FooC, FooA, FooB, FooA

依次按类型排序。

FooA, FooB, FooC, FooD, FooA, FooB, FooC, FooA, FooA

我正在尝试可以按照您指定的顺序订购该功能,在这种情况下,IE,它是:

new[] { typeof(FooA), typeof(FooB), typeof(FooC), typeof(FooD) }

我试图创建这个扩展,但我什么也没得到。你能帮忙一点吗?我猜我可以用 LINQ 完成它。

4

3 回答 3

6

您可以按类型对项目进行分组,按类型对组进行排序并交错组:

var groups = items.GroupBy(x => x.GetType())
                  .OrderBy(g => orderedTypes.IndexOf(g.Key))
                  .ToList();

var result = groups.First().Interleave(groups.Skip(1).ToArray());

使用来自 EvenMoreLINQ 的 Interleave 方法

foreach (var item in result)
{
    Console.WriteLine(item.GetType());
}

输出:

FooA
FooB
FooC
FooD
FooA
FooB
FooC
FooA
FooA
于 2012-08-25T20:22:32.063 回答
1

按类型分组,然后循环遍历项目以每次添加一组。就像是:

var groups =
  collection.GroupBy(x => x.GetType())
  .ToDictionary(g => g.Key, g => g.ToList());

List<Foo> result = new List<Foo>();
int max = groups.Values.Max(n => n.Count);
for (int i = 0; i < max; i++) {
  foreach (Type  t in sortArray) {
    if (groups[t].Count > i) {
      result.Add(groups[t][i]);
    }
  }
}
于 2012-08-25T20:28:33.310 回答
0

list是要排序的元素的集合。
pattern是按特定顺序排列的元素的集合。
resultlist根据 排序的元素的集合pattern

var list = new List<Foo> { new FooA(), new FooB(), new FooC(), new FooA(), new FooC(), new FooA(), new FooD() };
var pattern = new Foo[] { new FooB(), new FooC(), new FooD(), new FooA() };

var result = list.OrderBy(p => p, new MyFooComparer(pattern));

有一个MyFooComparer实现接口的类IComparer<>
比较是基于每个集合Foopattern集合中的位置。pattern元素不能重复,它们必须包含所有类型Foo(至少是 中使用的那些list)。
我曾经Dictionary<>存储模式顺序,因为它具有 O(1) 复杂度。

public class MyFooComparer : IComparer<Foo>
{
    private readonly Dictionary<Type, int> _pattern;
    public MyFooComparer(IEnumerable<Foo> pattern)
    {
        _pattern = new Dictionary<Type, int>();
        int i = 0;
        foreach (var foo in pattern)
        {
            _pattern.Add(foo.GetType(), i);
            i++;
        }
    }

    public int Compare(Foo x, Foo y)
    {
        var xVal = _pattern[x.GetType()];
        var yVal = _pattern[y.GetType()];
        return xVal.CompareTo(yVal);
    }
}

调用后:

        foreach (var foo in result)
        {
            Console.WriteLine(foo.GetType().Name);
        }

根据pattern,您将获得:

FooB
FooC
FooC
FooD
FooA
FooA
FooA

编辑:

扩展名List<Foo>

static class MyExtension
{
    public static IEnumerable<Foo> OrderByFoo<T>(this List<Foo> list, IEnumerable<Foo> patern)
    {
        return list.OrderBy(p => p, new MyFooComparer(patern));
    }
}
于 2012-09-04T13:46:31.810 回答