根据T的List <string>属性对List <t>进行排序

时间:2019-02-08 10:43:27

标签: c# list

我有一个自定义对象Deck,其属性之间有一个List<Card> cards。每个Card都有自己的List<string> colors,使用诸如[W, U, B, R, G]这样的一个或多个大写字母表示卡的颜色。

我需要做的是基于cards列表对colors列表进行排序,以这种方式,我首先从一种颜色获得所有卡片,以此类推。对于具有多种颜色的卡片,我希望根据自定义优先级列表对它们进行排序(例如将WU放在W张卡片之间),但是我意识到这是甚至更复杂,所以对我来说并不是真正的必要。

我想做的是

deck.cards = deck.cards.OrderBy(x => x.colors).ToList();

但是我收到一条错误消息,指出至少一个对象需要实现ICompare。

我可以对我的卡片组列表进行排序吗?

不仅可以像描述的那样对它进行排序,还可以根据B之前R之前的G等特定顺序进行排序?

2 个答案:

答案 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”