web-dev-qa-db-ja.com

オブジェクトのリストでmax属性の値を持つオブジェクトを取得します

これは私がこれまでに書いたコードであり、プログラムのポイントは、ファイルから20人を読み取り、それらに属性を割り当て、ユーザーからの入力から値を正規化することです。

class One:
    def __init__(self):
        self.attrOne = ()
        self.attrTwo = ()
        self.attrThree = ()
        self.attrFour = ()
        self.attrFive= ()
        self.attrSix = ()
        self.attrSeven = ()
        self.attrEight = ()
        self.attrNine = ()


class Two:

    def __init__(self):
        self.allPersons = []

   def importFromList(self, filename): 
       file= open(filename, "rU")
       for line in file:
           partOfList = line.split()                        
           x = Partner() 
           x.attrOne = partOfList[0]
           x.attrTwo = partOfList[1]
           x.attrThree = partOfList[2]
           x.attrFour = partOfList[3]
           x.attrFive = partOfList[4]
           x.attrSix = partOfList[5]
           x.attrSeven = partOfList[6]
           x.attrEight= partOfList[7]
           x.attrNine = partOfList[8]
           self.addPerson(x)
        file.close()

def addPerson(self, x):
    self.allPersons.append(x) 

私が疑問に思うのは、allPersonsリストに配置されている人物の属性をループし、それらを相互に比較して最大値を見つける方法です。これは私がこれまで試したものですが、動作させることができません

def getMaxValue(self): 
    o = One()
    for eachPartner in self.allPartners:
        maxValuesAttrOne = max(O.attrOne))

すべての助けに感謝します、そして私は新しい解決策を開いています、そしてまたimportFromListメソッドは最も効果的なものではないと思います、それであなたが何か異議を持ったら私は聞いて学びたいです!

14
Filip

max()keyパラメータを取ります。これは、オブジェクトの1つが渡されると、それらを比較するための値を返す関数です。

operator.attrgetter()を使用して、その値を取得します。

_from operator import attrgetter

max(self.allPartners, key=attrgetter('attrOne'))
_

これは、その属性が最大である一致するオブジェクトを返します。その最大値自体だけを保存したい場合は、2つのオプションがあります。

  • 返されたオブジェクトから属性を取得します。

    _max(self.allPartners, key=attrgetter('attrOne')).attrOne
    _
  • 代わりに、ジェネレータ式を使用してmax()に属性のみを渡します。

    _max(p.attrOne for p in self.allPartners)
    _

Oneクラスを同じ属性でさまざまな方向に何度も並べ替える必要がある場合(最小値、最大値を見つける、並べ替えるなど)、クラスを作成することをお勧めしますorderableも同様です。

これを行うには、 基本的なカスタマイズフック Python)のsomeを実装する必要があります=が検索します。いくつかの追加のトリックを使用すると、より低い操作と等しい操作だけで、 _funtools.total_ordering_クラスデコレータ を使用して回避できます。

_from functools import total_ordering

@total_ordering
class One:
    # ...
    def __lt__(self, other):
        if not isinstance(other, type(self)): return NotImplemented
        return self.attrOne < other.attrOne

    def __eq__(self, other):
        if not isinstance(other, type(self)): return NotImplemented
        return self.attrOne == other.attrOne
_

これで、Oneクラスは完全にattrOneに基づいて注文可能になりました。 max()関数の場合、これはkeyパラメーターを完全に削除できることを意味します。

38
Martijn Pieters