简体   繁体   中英

Sorting a list of objects, each containing a list

I'm writing a gin card game that deals with sets and melds of cards. A set is 3 or 4 cards with the same rank (ie 9c,9d,9h). A meld is a run of cards of the same rank (ie 8c,9c,10c). I want to sort a combined list of melds and sets.

Cards are represented like so:

class Card:
  def __init__(self, rank, suit):
    self.rank = rank
    self.suit = suit

Cards are stored in CardGroups like so:

class CardGroup:
  def __init__(self, card_list):
    self.cards = []
    for c in card_list:
      self.cards.append(c)

Here's an example with the hand 2c,2h,2d,4h,5d,5s,5c,6c,7c,8c:

The melds in this hand all deal with clubs: (5c,6c,7c) and (6c,7c,8c) . The sets are (2c,2d,2h) and (5c,5d,5s) .

The resulting combined list might combine like so (melds, then sets):

unsorted_list = [ CardGroup([Card(5,'c'), Card(6,'c'), Card(7,'c')], 
                  CardGroup([Card(6,'c'), Card(7,'c'), Card(8,'c')],
                  CardGroup([Card(2,'c'), Card(2,'d'), Card(2,'h')], 
                  CardGroup([Card(5,'c'), Card(5,'d'), Card(5,'s')] ]

The resulting combined list should exist like so (card by card comparison):

sorted_list   = [ CardGroup([Card(2,'c'), Card(2,'d'), Card(2,'h')], 
                  CardGroup([Card(5,'c'), Card(5,'d'), Card(5,'s')],
                  CardGroup([Card(5,'c'), Card(6,'c'), Card(7,'c')], 
                  CardGroup([Card(6,'c'), Card(7,'c'), Card(8,'c')] ]

Note that the second and third CardGroup both start with 5c . It is important that these are sorted correctly. In the case that we have a 4-set like 2c,3c,4c,5c we also implicitly have a 3-set of 2c,3c,4c . When sorting these two, we want the 3-set to come before the 4-set.

Things I've Tried:

unsorted_list.sort(key=lambda x: x.cards)
unsorted_list.sort(key=lambda x: x.cards[0])
unsorted_list.sort(key=lambda x: tuple(x.cards))

Thank you for the help!

Edit: Using a comparison operator was suggested as an answer. Here are the unit tests for such a solution:

Class TestCard:
    def test___cmp__(self):
        card1 = Card(5, 'd')
        card2 = Card(6, 'c')
        card3 = Card(6, 's')

        self.assertLessEqual(card1.__cmp__(card2), -1)
        self.assertLessEqual(card1.__cmp__(card3), -1)
        self.assertEqual(card1.__cmp__(card1), 0)

        self.assertGreaterEqual(card2.__cmp__(card1), 1)
        self.assertLessEqual(card2.__cmp__(card3), -1)

        self.assertGreaterEqual(card3.__cmp__(card1), 1)
        self.assertGreaterEqual(card3.__cmp__(card2), 1)

I believe this might help:

class Card:
  # ...
  def __cmp__(self, other):
    r = self.rank.__cmp__(other.rank)
    if not r:
      return self.suit.__cmp__(other.suit)
    return r

class CardGroup:
  # ...
  def __cmp__(self, other):
    return cmp(self.cards, other.cards)

Now you should be able to use just unsorted_list.sort() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM