2016-07-18 14 views
0

次のコードをPythonで持っています。ランクでカードを整理(グループ化)しています。私は古い学校の方法でこれをやったが、Pythonがそのようなことで実際に有名であるため、より良い方法があると確信している。 私はどのように短くてエレガントな方法で同じことをすることができますか?ここでpythonコードの改善 - リスト要素をプロパティ値でグループ化する方法

は、メソッドのコードです:

def gatherRanks(self, hand): 
     self.value1 = [] 
     self.value2 = [] 
     self.value3 = [] 
     self.value4 = [] 

     card1 = hand.cards[0] 
     self.value1.append(card1) 

     card2 = hand.cards[1] 
     if card2.rank == card1.rank: 
      self.value1.append(card2) 
     else: 
      self.value2.append(card2) 

     card3 = hand.cards[2] 
     if card3.rank == card1.rank: 
      self.value1.append(card3) 
     elif card3.rank == card2.rank: 
      self.value2.append(card3) 
     else: 
      self.value3.append(card3) 

     card4 = hand.cards[3] 
     if card4.rank == card1.rank: 
      self.value1.append(card4) 
     elif card4.rank == card2.rank: 
      self.value2.append(card4) 
     elif card4.rank == card3.rank: 
      self.value3.append(card4) 
     else: 
      self.value4.append(card4) 

     card5 = hand.cards[4] 
     if card5.rank == card1.rank: 
      self.value1.append(card5) 
     elif card5.rank == card2.rank: 
      self.value2.append(card5) 
     elif card5.rank == card3.rank: 
      self.value3.append(card5) 
     elif card5.rank == card4.rank: 
      self.value4.append(card5) 

その方法の背後にある考え方は、自分のランク(ないスーツ)によってグループカードにあります。私は4つの自己変数を持つことに決めました。なぜなら、それはリストよりも使いやすいからです。 理由は非常に簡単です:後で手をつかむ。ランク別にグループ化され 有するカードIは、簡単に、例えば、図形を確認することができる: - (ループが必要ストレート除く)コードの3行

#(checking if hand is a Trip) 
def isThreeOfKind(self, hand): 
     self.gatherRanks(hand) 
     return len(self.value1)==3 or len(self.value2)==3 or len(self.value3)==3 

等は、すべてのチェックが1の問題です。

+2

は、 'CodeReview'はあなたのための場所です。 http://codereview.stackexchange。com/ –

+0

カード5のランクが他のカードのランクと一致しない場合、4つのリストのいずれにも追加されません。それは意図的なものですか? –

+0

Rawingさんのコメントに続いて、私は自分の順位の代わりにスーツでカードをグループ化するべきだと思っています。そして、そういうことをするより効率的な方法があります。 –

答えて

0

self.value1self.value2などのリストを削除した場合にのみ、実際の改善が可能です。そのような変数を作成しているとわかるときは、代わりにリストを使用する必要があります。

次のコードは、(それがコードに関連していないですので、私はselfを省略)あなたが欲しいものを行います。

def gather(hand): 
    values= [] 

    for card in hand.cards: 
     #for each card, check if a list containing cards of the same rank already exists 
     for card_list in values: 
      if card_list[0].rank==card.rank: 
       #found one, add the card to this list 
       card_list.append(card) 
       break 
     else:#if no list with the same rank exists, create one 
      values.append([card]) 

    #and if you insist on having your 4 lists: 
    values1= values[0] if len(values)>0 else [] 
    values2= values[1] if len(values)>1 else [] 
    values3= values[2] if len(values)>2 else [] 
    values4= values[3] if len(values)>3 else [] 
+0

私は内部のループを実際に理解できないので、コメントするのは難しいです。あなたのコードは一般的には動作しますが、残念ながら何も集めないので、最終的な値の変数は常に空です。 – smoczyna

+0

@smoczynaこのコードは間違いなく動作します。テストするために 'Card'と' Hand'クラスを作成しました。おそらく 'values'の代わりに' self.values'変数を見ているのでしょうか? 'if card_list [0] .rank == card.rank'の行では、' card_list'は同じランクのカードのリストなので、 'card.rank'が同じならば、それに加えられますリスト。 –

+0

'values'が空である可能性がある唯一の方法は、' hand.cards'も空であるか、 'for ... in'ループで反復を許さない場合です。 –

0
  • PEP8
    • gather_ranks代わりに4つのスペースの代わりに8
  • 使用リスト/ dictsを使用gatherRanks
  • インデントとループは、それがよりコンパクトで、より読みやすくするため(及びエラーを起こしにくい)
  • docstringを追加する(私はNumpydocが好き)
  • 012だからここ

は、調整コードです:もちろん

def gather_ranks(self, hand): 
    self.value = [] 
    for i in range(4): 
     self.value.append([]) 

    # The first card always goes to the first hand 
    self.value[0].append(hand.cards[0]) 

    # Go through the next cards. Foreach card, check 
    # if the first hands card(s) has/have the same value. 
    # If so, add it there. Otherwiese go to the next hand. 
    # If none had the same, add it to the next players hand. 
    for card_index in [1, 2, 3, 4]: 
     for i in range(card_index): 
      if hand.cards[card_index].rank == hand.cards[i].rank: 
       self.value[i].append(hand.cards[card_index]) 
       break 
     else: 
      # loop fell through without break 
      # Card was not added to any player 
      if card_index < 5: 
       self.value[card_index].append(hand.cards[card_index]) 

私はこの背後にある意味があるのか​​分からないので、私は本当に良いコメントをすることはできません。あなたはこのゲームで意味をなさないものでこれを置き換える必要があります。

+0

に属しているため、この質問を議論の対象外としています。OPのコードはこれ以上読みやすいものでした。 –

+0

@Rawing私はいくつかの編集をしました。あなたはまだそう思っていますか? –

+0

はい、間違いなく。実際、あなたのコードは読みにくいのでIndexErrorが発生することに気付かなかった。 –

0

ランクの数は、変数の使用から判断すると、事前に決定されたように見えます自己。値1〜自己。値4。

実際そうであれば、辞書が便利になるかもしれません。

def gather_ranks(self, hand): 
    # initialize the dictionary with card ranks 
    # r1...r4 represents card ranks 
    self.ranked_cards = {"r1": [], "r2": [], "r3": [], "r4": []} 

    for card in hand.cards: 
     self.ranked_cards[card.rank].append(card) 
+0

それは5つのカードがあり、それぞれのランク(値)とスーツ(カラー)。目標は、カードをランク​​別にグループ化して、さらに見積もりを簡単に行うことです(上のポストを更新してください)。したがって、ランクを集めるためには、彼らをお互いに比較する必要があります。 – smoczyna

0

私はdefaultdict使用する

(編集例):現在のバージョンが動作していると、あなたは、単にそれを改善したい場合は

from collections import defaultdict 
from pprint import pprint 
import itertools 
import random 


class Card(object): 
    def __init__(self, rank_color): 
     self.rank, self.color = rank_color 
    def __repr__(self): 
     return '{} of {}'.format(self.rank, self.color) 

class Hand(object): 
    def __init__(self): 
     self.cards = [] 
     self.gathered_ranks = defaultdict(list) 
    def add_card(self, card): 
     self.cards.append(card) 
     self.gathered_ranks[card.rank].append(card) 
    def get_gathered_ranks(self): 
     return dict(self.gathered_ranks) 

if __name__ == '__main__': 
    hand = Hand() 

    colors = ['spade', 'club', 'heart', 'diamond'] 
    ranks = range(1, 15) 
    deck = [e for e in itertools.product(ranks, colors)] 
    random.shuffle(deck) 
    # We suppose players have 5 random cards 
    for i in range(5): 
     card = deck.pop() 
     hand.add_card(Card(card)) 
    pprint(hand.get_gathered_ranks()) 
+0

私はあなたがポイントを逃したと思う、全体のアイデアは、それらの値(ランク)でカードをグループ化することであり、すべてのカードはすでにシャッフルされています。私はすべてのプレイヤーの手がすでに召還されており、それぞれに5枚のカードがあることを意味します。 – smoczyna

+0

@smoczyna 'gatherRanks'によって返されるdictのキーはランクです。値は対応するランクのカードのリストです。 'if __name__ == '__main __':'の行は関数をテストするためのものです。 – Frodon

+0

@smoczyna例を変更しました:カードは追加されるたびにランクごとに集められます – Frodon

関連する問題