У меня есть функция, которая принимает объекты Card и должна сортировать их по строковому значению в произвольном порядке. Каждая карта может быть любым номером от 2 до 10 или J, Q, K или A. Я хочу, чтобы моя функция сортировала карты в следующем порядке: 2, 3, 4, 5, 6, 7, 8, 9, 10 , Дж, В, К, А.
Однако, если я попытаюсь отсортировать их с помощью OrderBy(x => x.Value) , они будут отсортированы по строке. У меня есть функция GetRankDictionary, потому что я думал, что это будет полезно, но я не вижу, можно ли использовать ее в лямбда-выражении для аргументов OrderBy.
class Program
{
public class Card
{
public string Value;
public string Suit;
public Card(string value, string suit)
{
Value = value;
}
}
static void Main(string[] args)
{
var cards = new List<Card>() { new Card("J", "Hearts"), new Card("8", "Hearts"), new Card("3", "Hearts"),
new Card("6", "Hearts"), new Card("9", "Hearts"), new Card("7", "Hearts"),
new Card("K", "Hearts"), new Card("A", "Hearts"), new Card("2", "Hearts")};
cards = SortCards(cards);
}
public static List<Card> SortCards(List<Card> cards)
{
var RankDictionary = GetCardRankDictionary();
// How to custom sort the cards in LINQ indicated by RankDictionary?
cards = cards.OrderBy(x => x.Value).ToList();
foreach (Card c in cards)
Console.WriteLine(c.Value);
return cards;
}
public static Dictionary<string, int> GetCardRankDictionary()
{
var dict = new Dictionary<string, int>();
var values = new string[] {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
var index = 2;
foreach (string s in values)
dict.Add(s, index++);
return dict;
}
}
Просто дайте вашему Card
дополнительное свойство Rank
, а затем отсортируйте по нему
Предложение @JohanP простое, и вам понадобится это свойство или другой список рангов. Некоторые предпочитают делать это с помощью интерфейсов IComparer<T>
и IComparable<T>
, stackoverflow.com/a/26868916/495455 — тогда можно использовать встроенную функцию сортировки.
@cad Я случайно пропустил 10. Спасибо, что заметили.
Это действительно очень просто. Ваш код был почти готов.
Попробуй это:
public static List<Card> SortCards(List<Card> cards)
{
var RankDictionary = GetCardRankDictionary();
cards = cards.OrderBy(x => RankDictionary[x.Value]).ToList();
foreach (Card c in cards)
Console.WriteLine(c.Value);
return cards;
}
public static Dictionary<string, int> GetCardRankDictionary() =>
new string[] { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" }
.Select((x, n) => (x, n))
.ToDictionary(z => z.x, z => z.n);
Выполнение этого на ваших примерах данных дает мне:
2
3
6
7
8
9
J
K
A
Вы можете добавить свойство
public int NumValue
к классу Cards, которое представляет значение карты с целым числом. Числа от «2» до «9» будут их соответствующим значением int, а «J» == 11, «Q» == 12 и т. д., установленными в конструкторе с помощью переключателя. Кстати, вы намеренно пропустили "10"? Другим решением может быть Comparer: learn.microsoft.com/en-us/dotnet/api/…