2016-06-24 14 views
0

私はいくつかの名前付き属性を持つPython 3.5.1のオブジェクトのリストを持っています。リストはC変数のグループを表し、各オブジェクトには3つの共通の基本タイプ(uint8、uint16、およびuint32)に対応する3つの名前付き属性があります。python3複数の名前付き属性によるオブジェクトの並べ替え

class variableList(object): 
    def __init__(self, eight, sixteen, thirtytwo): 
     self.size_8 = eight 
     self.size_16 = sixteen 
     self.size_32 = thirtytwo 

これらの名前付き属性の値が(Nonetype) None(str)'E'のいずれかです。オブジェクトごとに、指定された属性のうちの1つだけが非None値を持ちます。

このオブジェクトのリストをソートして、size_32以外の値でないすべてのオブジェクトが上にあり、その後にsize_16が続き、size_8が続くようにしたいとします。 python 2.7.1では

は私が成功し、これを使用しますが、それは黒魔術のように感じていない:

size_filtered_list = sorted(filtered_list, key=lambda y: (y.size_32, y.size_16, y.size_8)) 

が、3.5.1で、これはもはや機能します。提案?

+0

'__lt__'メソッドと' __eq__'メソッドを定義すると、 'key'引数なしで変数をソートすることができます。私はCに慣れていないので、基本的に ''(str) ''がPythonで何を意味するのかを説明できますか? –

+0

'False'と' True'を使うのではなく、効果的なブール値フラグを 'None'と' 'E''として使用している理由はありますか?互換性のない型を使用していなかった場合、ソートは 'sorted(filtered_list、key = attrgetter( 'size_32'、 'size_16')を使って、ファイルの先頭にある' from operator import attrgetter' 、 'size_8')) '、これはPythonのすべてのバージョンでうまく動作します。 – ShadowRanger

+0

また、 'self.size_8_exist'のように別の変数を追加しても、同じテクニックを使えます。 – arewm

答えて

0

私はクラスの比較演算子を実装するだけです。これらの属性のそれぞれに格納されている値に基づいてソートしたくない場合、この実装は機能するはずです。

class variableList(object): 
    def __init__(self, eight, sixteen, thirtytwo): 
     self.size_8 = eight 
     self.size_16 = sixteen 
     self.size_32 = thirtytwo 

    def __lt__(self, other): 
     if self.size_8 is not None: 
      return self != other 
     elif self.size_16 is not None: 
      return True if other.size_32 is not None else False 
     else: 
      return False 

    def __eq__(self, other): 
     if self.size_8 is not None: 
      return other.size_8 is not None 
     elif self.size_16 is not None: 
      return other.size_16 is not None 
     else: 
      return other.size_32 is not None 

万全を期すために、あなたはまた、オペレータよりも大きい実装することができますが、それはソートするために必要ではありません。

def __gt__(self, other): 
     if self.size_32 is not None: 
      return self != other 
     elif self.size_16 is not None: 
      return False if other.size_32 is not None else True 
     else: 
      return False 

あなたは同じ型の値をソートする場合は、必要になりますこれらの値を比較するために別のレベルの入れ子を追加する必要があります。

+0

Pythonソートでは '__lt__'だけを使用するという実装の詳細には決して依存しません。' functools.total_ordering'を使用して '__eq__'を一度作成し、そのうちの一つが定義されると、他の比較メソッドを自動生成できます。 –

+0

ありがとう、私はそれについて知らなかった。私は比較演算子で愚かな間違いをしたので、常に他人を自動化することは、自分ですべてを書くよりも好ましいでしょう。 – arewm

+0

あなたは正しいです。その場合、これははるかに欠陥の少ないようですが、依然として 'y = variableList(1、None、None); print(y

1

互換性のあるタイプの使用に移行する必要があります。ソートNone'E'は無意味であり、互換性のない型のPython 2の「任意で一貫した」ソート規則では許されていますが、それはひどい習慣です。唯一の値がNone'E'の場合、それらは実際にはブール値のひどいバージョンです。 FalseTrueを簡単に使うことができ、key関数はPy2とPy3の両方でうまく動作します。あなたは少しoperator.attrgetterでも、「最適化」できます。

また
from operator import attrgetter 

size_filtered_list = sorted(filtered_list, key=attrgetter('size_32', 'size_16', 'size_8')) 

、元lambdaベースのコードを使用して、あなたはkeyに空の文字列でNoneを置き換えることによって、それを動作させることができ、あなたは互換性のあるタイプを比較(中

size_filtered_list = sorted(filtered_list, key=lambda y: (y.size_32 or '', y.size_16 or '', y.size_8 or '')) 

それは一種の愚かなのですが、そうブールデータに相当するもののためにNone'E'を使用している:まだ)他のすべての文字列よりも少ないようNoneを処理します。

関連する問題