改进python代码 - 如何按属性值对列表元素进行分组

时间:2016-07-18 08:12:03

标签: python

我在Python中有以下代码,它按照他们的级别组织(分组)扑克牌。我是以老派的方式做到这一点,但我确信有更好的方法,因为Python实际上是着名的那种东西。 我怎样才能以更短更优雅的方式做同样的事情?

以下是方法代码:

autocomplete="nope"

这种方法背后的想法是按照他们的RANK(不适合)对牌进行分组。我还决定有4个自变量,因为它比列表更容易使用。 原因很简单:稍后弄清楚手。 按照按行分组的卡片我可以轻松检查图形,例如:

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)

等等,每次检查都需要1-3行代码(Straight除外,需要循环)。

4 个答案:

答案 0 :(得分:0)

  • PEP8
    • gatherRanks代替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])
    • 缩进使用4个空格而不是8个
  • 使用lists / dicts和for循环使其更紧凑,更易读(并且不易出错)
  • 添加文档字符串(我喜欢Numpydoc

所以这是经过调整的代码:

    //PK
    @Entity
    @Table(name="s_c_bur_dtl")
    public class SurveyConductBurglaryDetails {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO,generator="surveycondbgdtl_seq")
        @javax.persistence.SequenceGenerator(name="surveycondbgdtl_seq",sequenceName="surveycondbgdtl_seq",allocationSize=1,initialValue=1)
        @Column(name = "nsurveycondbgdtlcd", unique=true, nullable = false, columnDefinition = "bigint")
        private BigInteger surveyCondBgDtlCd;


        @OneToMany(cascade = CascadeType.ALL,mappedBy="surveyConductBurglaryDetails")
        private List<SurveyConductBurglaryProperty> surveyConductBurglaryProperties;

    }

    //FK
    @Entity
    @Table(name="s_c_bur_property")
    public class SurveyConductBurglaryProperty {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO,generator="surveycondbgproperty_seq")
        @javax.persistence.SequenceGenerator(name="surveycondbgproperty_seq",sequenceName="surveycondbgproperty_seq",allocationSize=1,initialValue=1)
        @Column(name = "nsurveycondbgpropertycd", unique=true, nullable = false, columnDefinition = "bigint")
        private BigInteger surveyCondBgPropertyCd;

        @ManyToOne
        @JoinColumn(name = "nsurveycondbgdtlcd")        
        private SurveyConductBurglaryDetails surveyConductBurglaryDetails;

    }   

 @Service
    class SaveService{
     @Autowired DbService dbService;

    public void conductSurvey(SurveyConductBurglaryDetails surveyConductBurglaryDetails) throws IllegalAccessException, InvocationTargetException{

        dbService.saveOrUpdate(surveyConductBurglaryDetails); // call for save

    }
    }

    @Service
    class DbService{
    public void saveOrUpdate(Object insertObj){

            Session session = surveyTransactionManager.getSessionFactory().getCurrentSession();
            Transaction transaction = session.getTransaction();
            if(!transaction.isActive()){
                session.beginTransaction();
            }

            try{
                session.saveOrUpdate(insertObj);
                transaction.commit();

            }catch(Exception e){

                transaction.rollback();
                // TODO Auto-generated catch block
                if(logger.isDebugEnabled()){
                    logger.debug("SurveyDBService.saveOrUpdate Catch block");
                }
                e.printStackTrace();
            }finally{

            }


        }

    }

当然,我不能做出很好的评论,因为我不知道这背后的含义是什么。你应该用这个游戏中有意义的东西来替换它。

答案 1 :(得分: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 []

答案 2 :(得分:0)

从使用变量self.value1到self.value4来判断,排名的数量是预先确定的。

如果事实确实如此,字典可以派上用场。

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)

答案 3 :(得分: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())