2012-09-27 13 views
7

私はnamedtupleクラスをたくさん使っています。このようなクラスのカスタムソートを実装する良い方法がある場合、つまり、デフォルトのソートキーを名前付きタプルの最初の要素(2番目、3番目など)にしないと、私は今日考えています。 、名前付きタプルクラスのカスタムソート

def test_sortingB(): 
    b1 = B(1, 2) 
    b2 = B(2, 1) 
    assert b2 < b1 # passes 
    assert b2 <= b1 # fails 

ああ:しかし

from collections import namedtuple 
from functools import total_ordering 


@total_ordering 
class B(namedtuple('B', 'x y')): 
    def __lt__(self, other): 
     return self.y < other.y 

私の最初の本能は__lt____eq__を実装し、total_orderingが残り(それがルを記入、NE、GT、GE)をやらせることでした右... total_orderingは、他の方法を記入してくださいif they are missing。 tuple/namedtupleにはこのようなメソッドがあるので、total_orderingは私のために何もしません。

だから私は私のオプションがnamedtupleを使用して

  1. 停止していると思いますし、ちょうどnamedtupleとインサートを使用してキープし、私自身の退屈なクラスを構築namedtupleを使用してtotal_ordering
  2. キープを使用しておくと、すべての6つの比較方法に
  3. を実装最初のフィールドとしてのソート値。幸いにも、私はクラスのインスタンスがあまり多くありませんが、通常、フィールドの順序を頼りにして初期化してしまうと厄介になります。たぶんそれは悪い習慣です。

これを解決するにはどうすればよいですか?

+0

並べ替え順のフィールドを持つ名前付きタプルを作成しないのはなぜですか? – BrenBarn

+0

私はすでにそれを作成してしばらく使っていない限り、私はそれをソート/マックスしたいとは思いませんでした。だから、先行フィールドをソートフィールドに追加することができましたが、少し混乱する可能性があります。 – pfctdayelise

+1

しかし、名前付きタプルはどのように使用していますか?namedtupleの便利な点は、名前でアイテムにアクセスできるようにするため、フィールド名にアクセスする限り、名前付きタプルを変更して正しい順序でフィールドを持ち、コードに影響を与えないようにすることができます(おそらくそうでなければnamedtupleを使う理由は?)。 – BrenBarn

答えて

10

OPTION 1. mixinとその

にtotal_orderingを適用
@total_ordering 
class B_ordering(object): 
    __slots__ =()     # see Raymond's comment 
    def __lt__(self, other): 
     return self.y < other.y 

class B(B_ordering, namedtuple('B', 'x y')): 
    pass 

オプション2. total_orderingに基づいて独自のデコレータを作成し、代わりに

+1

+1、mixin溶液がいいです。 – nneonneo

+0

オプション1とオプション2のオーバーヘッドに大きな違いはありますか? – Will

+0

+1。オプション1は、total_orderingに欠損値を埋め込むという問題に対する直接的な解決策です。 @ Willオプション1のオーバヘッドはほとんどゼロです(メソッドの解決の順序で1つの追加ステップ)。@ JohnLaRooy、メモリ効率を回復するためにOption1に\ _ \ _ slots \ _ \ _ =()を追加することをお勧めします –

1

私の助言は、それらがソートされるように、別のフィールドに名前付きタプルを作成することです。値を作成するコードの部分を変更する必要があるかもしれません(たとえば、someTuple("name", 24)からsomeTuple(24, "name")に変更します)が、一般的に値は使用されるよりも少ない場所で作成されるため、これはあまり大きな問題ではありません。すべての比較方法を書く手間を回避し、ボーナスとしても、すべての時間と呼ばれるこれらのカスタム比較メソッドを持つの追加のパフォーマンス・オーバーヘッドを回避できます。

3

あなたの質問が示すように、あなたの関心が代替キーによってのみソート namedtuplesであり、なら、なぜソートを使用していない/ attrgetter機能をkey引数を並べ替え:

>>> from collections import namedtuple 
>>> from operator import attrgetter 
>>> P = namedtuple("P", "x y") 
>>> p1 = P(1, 2) 
>>> p2 = P(2, 1) 
>>> sorted([p1, p2], key=attrgetter("y")) 
[P(x=2, y=1), P(x=1, y=2)] 

あなたも行くことができます

>>> from functools import partial 
>>> sortony = partial(sorted, key=attrgetter("y")) 
>>> sortony([p1, p2]) 
[P(x=2, y=1), P(x=1, y=2)] 
+0

ソートフィールドまだ存在していないので、追加するか、2つのフィールドを参照して、それらについて少しの論理を行うcmpメソッドを使用する必要があります(私のコード例はあまり単純化されています) – pfctdayelise

関連する問題