用c ++自定义排序字符串

时间:2018-05-16 09:23:21

标签: c++ list sorting

我在自定义排序字符串方面遇到了一些问题。我基本上拥有std::list std::pair,其元素为enum classstd::string Enum 用于颜色(正确排序)和字符串包含[2,10]间隔中的数字,分别添加字母J,Q,K和A.正如您可能已经猜到的那样,它是一副卡片,在排序后必须看起来像这样: 2,3,4,5,6,7,8,9,10,J,Q,K,A。

为了达到这个目的,我的lambda函数应该是什么样的?或者还有另一种方式吗?

到目前为止,这是我的竞争对手:

enum class Colours
{
Spades, Clubs, Hearts, Diamonds
};

typedef std::list<std::pair<Colours, std::string>> Deck;
typedef std::pair<Boje, std::string> Pair;

这是实际的排序:

deck.sort( [] (const Pair &x, const Pair &y) -> bool {
        if(x.first == y.first) return x.second < y.second;
        else return x.first < y.first;
    } );

目前的排序结果:10 2 3 4 5 6 7 8 9 A J K Q

5 个答案:

答案 0 :(得分:3)

你要做的一件事是每个string的第一个字符是唯一的。此代码未经测试,但应该接近:

unsigned int face_value(std::string const &face) {
    if(std::isdigit(face[0])) {
        // if the length is 1 we just need the digit
        if(face.length() == 1) {
            return face[0] - '0';
        }
        // if it's not 1, it has to be 10
        return 10;
    }
    switch(face[0]) {
    case 'J':
        return 11;
        break;

    case 'Q':
        return 12;
        break;

    case 'K':
        return 13;
        break;

    case 'A':
        return 14;
        break;

    default:
        assert(false);
        break;
    }
}

bool face_compare(std::string const &first, std::string const &second) {
    return face_value(first) < face_value(second);
}

使用辅助函数,lambda是微不足道的:

deck.sort( [] (const Pair &x, const Pair &y) -> bool {
    return std::tie(x.first, face_value(x.second)) <
           std::tie(y.first, face_value(y.second));
});

作为旁注,我的猜测是你想在Colour之前比较面值,但我现在仍然坚持原始逻辑。

答案 1 :(得分:3)

您可以查看卡片的面值,表示为std::map<std::string, int>。我们可以使用std::tuple小于std::tie,而不是明确指定少于两个值。

// throws std::out_of_range if not passed a valid face
int face_value (const std::string & face)
{
    static const std::map<std::string, int> faces {
        { "2", 2 },  { "3", 3 },  { "4", 4 },
        { "5", 5 },  { "6", 6 },  { "7", 7 },
        { "8", 8 },  { "9", 9 },  { "10", 10 },
        { "J", 11 }, { "Q", 12 }, { "K", 13 },
        { "A", 14 },
    }

    return faces.at( face );
}

deck.sort( [] (const Pair &x, const Pair &y) -> bool {
    return std::tie(x.first, face_value(x.second)) < std::tie(y.first, face_value(y.second));
} );

答案 2 :(得分:0)

由于10小于2,因此1小于2,因此不会按照您想要的方式进行排序。使用类和比较运算符可能会更好:

struct Card {
    enum class Suite { Spades, Clubs, Hearts, Diamonds};

    operator<(const Card& other) {
        if (suite == other.suite) { return number < other.number; }
        return suite < other.suite;
    }

    string toString(); // Function to make your card string representation.

    private:
       int number; // 2 - 14 (11, 12, 13, 14: J, Q, K, A)
       Suite suite;
}

然后你可以这样做:

std::list<Card> myList;
myList.sort();

注意:未经测试的代码,也需要适当的构造函数转换器等。

答案 3 :(得分:0)

问题在于您要比较string s,即按字母顺序比较它们。让我们看看哪些比较会产生不好的结果:

  

2,3,4,5,6,7,8,9与10

     

J vs A

     

Q vs K

     

K vs A

因此,您需要编写比较以检查是否有任何值为10,A或J.如果是10,请检查另一个是否为数字。如果是A,检查另一个是J还是K.如果是K,检查另一个是Q还是A.如果满足任何一种情况,则返回符合您需要的逻辑值。否则像以前一样工作:

deck.sort( [] (const Pair &x, const Pair &y) -> bool {
        if(x.first == y.first) {
            //Here you need to implement your custom cases as described above
            return x.second < y.second;
        }
        else return x.first < y.first;
    } );

答案 4 :(得分:0)

关于诉讼和价值的枚举如何:

enum class Suit {
    Spades, Clubs, Hearts, Diamonds
};

enum class Val {
    v2, v3, v4, v5, v6, v7, v8, v9, v10, vJ, vQ, vK, vA
};

typedef std::pair<Suit, Val> Pair;

然后,如果你想要它,打印Pair

的方法
std::string GetCardName(Pair p)
{
    std::string suit_name;
    switch (p.first)
    {
        case Suit::Spades : suit_name = "Spades"; break;
        /* ... */
        case Suit::Diamonds : suit_name = "Diamonds"; break;
    }

    std::string val_name;
    switch (p.second)
    {
        case Val::v2 : val_name = "2"; break;
        case Val::v3 : val_name = "3"; break;
        /* ... */
        case Val::vA : val_name = "Ace"; break;
    }

    return val_name + " of " + suit_name;
}

然后你可以完全按照你最初的写作进行比较,因为Suit和Val枚举是隐式排序的:

std::list<Pair> Deck =
{
    std::make_pair(Suit::Spades, Val::vA),
    std::make_pair(Suit::Clubs, Val::v7)
};

Deck.sort( [](const Pair& p1, const Pair& p2)
{
    if(p1.first == p2.first) return p1.second < p2.second;
    else return p1.first < p2.first;
} );

for (const auto& pair : Deck)
{
    std::cout << GetCardName(pair) << std::endl;
}

输出:

Ace of Spades
7 of Clubs

这是整个事情的minimal working example