我有一个自定义对象Deck
,其属性之间有一个List<Card> cards
。每个Card
都有自己的List<string> colors
,使用诸如[W, U, B, R, G]
这样的一个或多个大写字母表示卡的颜色。
我需要做的是基于cards
列表对colors
列表进行排序,以这种方式,我首先从一种颜色获得所有卡片,以此类推。对于具有多种颜色的卡片,我希望根据自定义优先级列表对它们进行排序(例如将W
和U
放在W
张卡片之间),但是我意识到这是甚至更复杂,所以对我来说并不是真正的必要。
我想做的是
deck.cards = deck.cards.OrderBy(x => x.colors).ToList();
但是我收到一条错误消息,指出至少一个对象需要实现ICompare。
我可以对我的卡片组列表进行排序吗?
不仅可以像描述的那样对它进行排序,还可以根据B
之前R
之前的G
等特定顺序进行排序?
答案 0 :(得分:3)
根据评论中的讨论,当卡片具有多种颜色时,您想要选择一种颜色(在优先级列表中首先出现的一种颜色),并在此基础上对其进行排序。
// Higher-priority colours come first
var coloursPriority = new List<string>() { "W", "U", "B", "R", "G" };
// Turn the card's colour into an index. If the card has multiple colours,
// pick the smallest of the corresponding indexes.
cards.OrderBy(card => card.Colours.Select(colour => coloursPriority.IndexOf(colour)).Min());
回应评论中的讨论:如果您要首先根据卡片的最高优先级颜色对它们进行排序,然后按其次高的颜色进行排序,等等。一种合理有效的方法:
public class CardColourComparer : IComparer<List<int>>
{
public static readonly CardColourComparer Instance = new CardColourComparer();
private CardColourComparer() { }
public int Compare(List<int> x, List<int> y)
{
// Exercise for the reader: null handling
// For each list, compare elements. The lowest element wins
for (int i = 0; i < Math.Min(x.Count, y.Count); i++)
{
int result = x[i].CompareTo(y[i]);
if (result != 0)
{
return result;
}
}
// If we're here, then either both lists are identical, or one is shorter, but it
// has the same elements as the longer one.
// In this case, the shorter list wins
return x.Count.CompareTo(y.Count);
}
}
然后
// Higher-priority colours come first
var coloursPriority = new List<string>() { "W", "U", "B", "R", "G" };
cards.OrderBy(card =>
card.Colours.Select(colour => coloursPriority.IndexOf(colour)).OrderBy(x => x).ToList(),
CardColourComparer.Instance);
这利用了OrderBy
仅将keySelector
委托应用于每个项目的事实。我们使用它来将每张卡变成一个包含其每种颜色的优先级的列表(优先级越高,值越低),然后按优先级顺序排列。然后,我们使用一个自定义比较器对这些键进行排序,该比较器将比较这两个列表。
请注意,这并不关心与每张卡相关的颜色顺序:[W, U]
的排序方式与[U, W]
相同。要考虑到顺序(因此[W]
早于[W, U]
早于[U, W]
,请执行以下操作:
cards.OrderBy(card =>
card.Colours.Select(colour => coloursPriority.IndexOf(colour)).ToList(),
CardColourComparer.Instance);
答案 1 :(得分:1)
您可以通过使用Aggregate函数来获得订购卡的列表,如下所示:
var result = deck.Cards
.OrderBy(x => x.Colours.Aggregate((total, part) => total + part.ToLower()))
.ToList();
这假设具有多种颜色的卡片在有序列表中。
例如
card1.Colours = new List<string>() { "W", "X" };
card2.Colours = new List<string>() { "W" };
card3.Colours = new List<string>() { "U" };
card4.Colours = new List<string>() { "U", "W" };
将按以下顺序退回卡片:
“ U”,“ UW”,“ W”,“ WX”