我有这样的集合,
Class Base{}
Class A : Base {}
Class B : Base {}
List<Base> collection = new List<Base>();
collection.Add(new A());
collection.Add(new B());
collection.Add(new A());
collection.Add(new A());
collection.Add(new B());
现在我想根据类型(A / B)对集合进行排序。我怎么能这样做?请帮帮我。
答案 0 :(得分:8)
您可以使用类型信息本身:
collection.Sort( (a,b) =>
{
bool aType = a.GetType() == typeof(A);
bool bType = b.GetType() == typeof(A);
return aType.CompareTo(bType);
});
这适用于您指定的两种类型,但不会超出它们。它允许您明确指定顺序(即:如果您想要“A”之前的“B”元素,您可以使用此技术使其工作)。
如果您需要支持多种类型,并且不需要提前指定排序,您可以执行以下操作:
collection.Sort( (a,b) => a.GetType().FullName.CompareTo(b.GetType().FullName) );
这将处理任意数量的类型(即:C和D子类型),并按其完整类型名称对它们进行排序。
答案 1 :(得分:6)
private static int OrderOnType(Base item)
{
if(item is A)
return 0;
if(item is B)
return 1;
return 2;
}
然后从以下选择:
collection.OrderBy(OrderOnType)
或
collection.Sort((x, y) => OrderOnType(x).CompareTo(OrderOnType(y)));
取决于您是否需要就地排序。如果你真的想要的话,你可以将OrderOnType放入lambda中,但这对我来说似乎更具可读性,我更喜欢在添加时保留lambdas而不是降低可读性。
答案 2 :(得分:4)
collection.OrderBy(i => i.GetType() == typeof(A) ? 0 : 1);
将为您提供包含所有A
s然后所有B
s
答案 3 :(得分:1)
确实
collection.Where(entry => entry is A).Concat(collection.Where(entry => entry is B))
做你需要的吗?
答案 4 :(得分:1)
这是订单,因此A
将是第一个,B
是第二个。
var xx = list.OrderBy(x => x.GetType() == typeof(B)).ToList();
以下控制台项目确认:
class Program
{
public class X { }
public class A : X { }
public class B : X { }
static void Main()
{
List<X> list = new List<X>();
list.Add(new B());
list.Add(new A());
list.Add(new B());
list.Add(new A());
list.Add(new A());
// A.GetType() == typeof(B) will be "0" making the type A go first
// B.GetType() == typeof(B) will be "1" making the type B go last
var xx = list.OrderBy(x => x.GetType() == typeof(B)).ToList();
Console.ReadLine();
}
}
在这种情况下,我假设您只有A
和B
。如果您有更多类型,则必须创建比较器以返回每种类型的值。你也可以在基类上有一个属性来设置元素的顺序,然后你可以用这个属性对列表进行排序。
答案 5 :(得分:0)
编辑:我认为这就是你想要的:
如果您不介意排序“不合适”并重新分配列表,这应该有效:
collection = collection.GroupBy(item => item.GetType())
.SelectMany(g => g)
.ToList();
或根据您的需要,例如:
collection = collection.OrderBy(item => item.GetType().FullName)
.ToList();
如果必须就地,那么编写自定义比较器和list.Sort
可能是最好的选择。
要按类别对项目进行分组,您可以使用GroupBy
:
var groupedItems = collection.GroupBy(item => item.GetType());
这使用延迟执行。
或者,您可以将'groups'放入如下的数据结构中:
var itemsByTypeLookUp = collection.ToLookup(item => item.GetType());
foreach(A a in itemsByTypeLookUp[typeof(A)])
{
...
}
如果您只是寻找某种类型:
var itemsOfTypeA = collection.OfType<A>();
答案 6 :(得分:0)
这样的事对我有用。
> Successfully compiled asm.js code (loaded from cache in 21ms)
> pre-main prep time: 0 ms
> Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value 33554432, (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.
> uncaught exception: abort() at wa@https://webencoder.libbpg.org/js/bpgdec8.js:19:34
> B@https://webencoder.libbpg.org/js/bpgdec8.js:85:320
> z.b@https://webencoder.libbpg.org/js/bpgdec8.js:11:48
> Z@https://webencoder.libbpg.org/js/bpgdec8.js:53:333
> Vd@https://webencoder.libbpg.org/js/bpgdec8.js:70:1
> fd@https://webencoder.libbpg.org/js/bpgdec8.js:70:1
> sd@https://webencoder.libbpg.org/js/bpgdec8.js:70:1
> Mc@https://webencoder.libbpg.org/js/bpgdec8.js:70:1
> Sc@https://webencoder.libbpg.org/js/bpgdec8.js:70:1
> Tc@https://webencoder.libbpg.org/js/bpgdec8.js:70:1
> _b@https://webencoder.libbpg.org/js/bpgdec8.js:66:1 Kb@https://webencoder.libbpg.org/js/bpgdec8.js:66:1
> Pc@https://webencoder.libbpg.org/js/bpgdec8.js:70:1
> Pd@https://webencoder.libbpg.org/js/bpgdec8.js:70:1
> Kd@https://webencoder.libbpg.org/js/bpgdec8.js:70:1
> @https://webencoder.libbpg.org/js/bpgdec8.js line 15 > eval:1:84
> window.BPGDecoder.prototype.load/d.onload@https://webencoder.libbpg.org/js/bpgdec8.js:88:216 If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.
> Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value 33554432, (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.
我的代码:
collection.OrderBy(p => p.GetType().Equals(typeof(B))).ThenBy(p => p.GetType().Equals(typeof(A))).ToList();
答案 7 :(得分:0)
这是稍后的答案,但一些简单的方法可能对其他人有用,并且在我的测试过程中可以实现类似的东西
var orderedList = animalList.OrderBy(x=> x.GetType().Name);
foreach(var animal in orderedList)
{
System.Console.WriteLine(animal.Name);
}
输出如下:
Ape
Ape
Ape
Ape
Cat
Cat
Cat
Cat
Cat
Dog
Dog
Dog
Dog
Dog
其中的animalList类似于:
animalList = new List<IAnimal>();
和IAnimal接口/实现:
public class Ape : IAnimal
{
public string Name => "Ape";
public AnimalType AnimalType => AnimalType.Ape;
}
public class Dog : IAnimal
{
public string Name => "Dog";
public AnimalType AnimalType => AnimalType.Dog;
}
public class Cat : IAnimal
{
public string Name => "Cat";
public AnimalType AnimalType => AnimalType.Cat;
}
public interface IAnimal
{
string Name {get;}
AnimalType AnimalType {get;}
}
此外,诸如指定代表您的课程顺序的枚举类型之类的方法可能会有所帮助。示例:
public enum MyOrderType
{
Ape = 1,
Cat = 2,
Dog = 3
}
那么就像
一样简单var orderedList = animalList.OrderBy(x=> x.AnimalType).ToList();