Как сравнивать два числа из списков List, если они с дополнительным символом?

У меня есть два списка

var list1 = new List<string>(6) и var list2 = new List<string>(6),

в них находятся данные, числа с буквами,

например: 5f, 3d, 6c и т.д.

Как мне сравнить данные из двух списков так, чтобы сравнивать можно было только числа с одинаковыми буквами,

например 5f и 6f, и чтобы программа понимала что 6f > 5f.

Я пробовал конвертировать

Convert.ToInt32(list1[0]) и писать условия if (list1[0]>list2[0]) ...

Но выдаёт ошибку, что нельзя сравнивать значения типа string и string


Ответы (2 шт):

Автор решения: Dev18

По-моему для вашей задачи, где нужно сравнивать строки с числами и буквами, регулярное выражение отлично подходит(?).

(\d+)([a-zA-Z]) поможет нам выделить числа и масти. В (\d+) захватываются все цифры до буквы, а [a-zA-Z] — буквенная часть масти

Нам необходимо извлечь число и "масть" отдельно.

Предложу такое решение:

  1. Сначала применим регулярное выражение (\d+)([a-zA-Z]), чтобы выделить две группы: первую (числовую) и вторую (буквенную), как и сказала выше. Числовая часть поможет нам определить порядок, а буквенная — проверить, что элементы принадлежат ли одной "масти"

  2. Если буквы совпадают, тогда можно сравнивать числа, чтобы определить, какой элемент больше. Если буквы не совпадают, такие элементы пропускаются, так как они принадлежат разным мастям и не подлежат сравнению

  3. добавила в список еще "несравнимые" эллементы (в условиях не говорится об этом), как просто цифры, или просто буквы, чтоб проверить, можете опустить эту часть //но уменя еще вопрос возник, а что если в списке1 есть 5d 4d и в списке2 6d, как сравнивать? Пока что мы сравниваем подряд, если не подходит проходим дальше, но надо ли "по всему" листу пройтись, чтоб его другие "масти" найти

вот сам код

using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        var list1 = new List<string> { "10f", "3d", "xyz", "6c", "5d", "5" };
        var list2 = new List<string> { "9f", "4d", "5c", "abc", "7d", "8" };

        int maxLength = Math.Max(list1.Count, list2.Count);
        var regex = new Regex(@"(\d+)([a-zA-Z])");

        for (int i = 0; i < maxLength; i++)
        {
            if (i < list1.Count && i < list2.Count)
            {
                var match1 = regex.Match(list1[i]);
                var match2 = regex.Match(list2[i]);

                if (!match1.Success || !match2.Success)
                {
                    Console.WriteLine($"Skipping comparison for {list1[i]} and {list2[i]}: format mismatch.");
                    continue;
                }

                try
                {
                    int num1 = int.Parse(match1.Groups[1].Value);
                    int num2 = int.Parse(match2.Groups[1].Value);
                    string suit1 = match1.Groups[2].Value;
                    string suit2 = match2.Groups[2].Value;

                    if (suit1 == suit2)
                    {
                        string result = num1 > num2 ? ">" : "<";
                        Console.WriteLine($"{list1[i]} {result} {list2[i]}");
                    }
                    else
                    {
                        Console.WriteLine($"Cannot compare {list1[i]} and {list2[i]}: different suits.");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error processing elements {list1[i]} and {list2[i]}: {ex.Message}");
                }
            }
            else if (i < list1.Count)
            {
                Console.WriteLine($"Element {list1[i]} is only in the first list.");
            }
            else if (i < list2.Count)
            {
                Console.WriteLine($"Element {list2[i]} is only in the second list.");
            }
        }
    }
}

консоль

10f > 9f
3d < 4d
Skipping comparison for xyz and 5c: format mismatch.
Skipping comparison for 6c and abc: format mismatch.
5d < 7d
Skipping comparison for 5 and 8: format mismatch.
→ Ссылка
Автор решения: Uranus

Добавлю решение использующее ООП подход. Инкапсулируем логику сравнения и парсинга строки, создав структуру с полями для хранения значения и масти отдельно друг от друга. Таким образом, вы можете реализовать перегрузку операторов >, < и == для удобного сравнения объектов.

Удобство такого подхода в том, что вы можете легко переопределить логику обработки ситуации, когда сравниваются карты с разными мастями. В примере я покажу простейший наивный подход, ибо нет смысла гадать какая логика нужна в вашем приложении. Главное - передать мысль.

Для простоты, будем подразумевать что формат строки, описывающий карту фиксированный. Она должна состоять из числа, за которым следует одна и только одна буква. Таким образом, можно будет обойтись без регулярных выражений. Ибо решение с регулярными выражениями уже показано в ответе Dev18. Вот пример кода:

using System;
using System.Collections.Generic;

struct Card : IComparable<Card>
{
    public int Value { get; }
    public char Suit { get; }

    public Card(string card)
    {
        if (string.IsNullOrEmpty(card) || card.Length < 2)
            throw new ArgumentException("Некорректный формат карты");

        // Парсим значение и масть
        Suit = card[^1];
        if (!int.TryParse(card[..^1], out int value))
            throw new ArgumentException("Некорректный формат значения карты");
        
        Value = value;
    }

    // Перегрузка оператора ">"
    public static bool operator >(Card c1, Card c2) => c1.Suit == c2.Suit && c1.Value > c2.Value;

    // Перегрузка оператора "<"
    public static bool operator <(Card c1, Card c2) => c1.Suit == c2.Suit && c1.Value < c2.Value;

    // Перегрузка оператора "=="
    public static bool operator ==(Card c1, Card c2) => c1.Suit == c2.Suit && c1.Value == c2.Value;

    // Перегрузка оператора "!="
    public static bool operator !=(Card c1, Card c2) => !(c1 == c2);

    // Переопределение методов Equals и GetHashCode
    public override bool Equals(object obj) => obj is Card card && this == card;

    public override int GetHashCode() => HashCode.Combine(Value, Suit);

    // Реализация интерфейса IComparable для сортировки
    public int CompareTo(Card other)
    {
        if (Suit != other.Suit)
            throw new InvalidOperationException("Карты разных мастей не могут быть сравнены");

        return Value.CompareTo(other.Value);
    }

    public override string ToString() => $"{Value}{Suit}";
}

class Program
{
    static void Main()
    {
        var list1 = new List<Card> { new Card("5f"), new Card("3d"), new Card("6c") };
        var list2 = new List<Card> { new Card("6f"), new Card("7d"), new Card("4c") };

        CompareLists(list1, list2);
    }

    static void CompareLists(List<Card> list1, List<Card> list2)
    {
        foreach (var card1 in list1)
        {
            foreach (var card2 in list2)
            {
                if (card1.Suit == card2.Suit)
                {
                    if (card1 > card2)
                        Console.WriteLine($"{card1} > {card2}");
                    else if (card1 < card2)
                        Console.WriteLine($"{card1} < {card2}");
                    else
                        Console.WriteLine($"{card1} == {card2}");
                }
            }
        }
    }
}

консоль

5f < 6f
3d < 7d
6c > 4c
→ Ссылка