Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to order a list by type?

Imagine that you have a list called List<Foo>.

Foo is an abstract class, so this can be FooA, FooB, FooC or FooD. And I'd like to have an extension for List<T> where you can order this elements by type but sequently.

For example, if I have 9 elements in it.

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

Order by type sequently will be.

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

I'm trying that the function can be ordered at the order you specify, at this case, IE, it was:

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

I was trying to create this extension, but I don't get anything. Can you help a little bit? I'm guessing that I can accomplish it with LINQ.

like image 480
Darf Zon Avatar asked Aug 25 '12 20:08

Darf Zon


2 Answers

You can group the items by type, sort the groups by type and interleave the groups:

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

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

using the Interleave method from EvenMoreLINQ.

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

Output:

FooA
FooB
FooC
FooD
FooA
FooB
FooC
FooA
FooA
like image 74
dtb Avatar answered Oct 05 '22 05:10

dtb


Group on the type, then loop through the items to add one set each time. Something like:

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]);
    }
  }
}
like image 39
Guffa Avatar answered Oct 05 '22 04:10

Guffa