web-dev-qa-db-ja.com

Python=

このような名前の質問がいくつかあることは知っていますが、彼らの答えが機能するようには思えません。

リストのリストがあり、50の5つの要素があります。次に、カスタム比較関数を各要素に適用して、このリストをソートします。この関数は、要素をソートするリストの適合度を計算します。比較とフィットネスの2つの関数を作成しました。

def compare(item1, item2):
    return (fitness(item1) < fitness(item2))

そして

def fitness(item):
    return item[0]+item[1]+item[2]+item[3]+item[4]

それから私はそれらを呼び出すことを試みました:

sorted(mylist, cmp=compare)

または

sorted(mylist, key=fitness)

または

sorted(mylist, cmp=compare, key=fitness)

または

sorted(mylist, cmp=lambda x,y: compare(x,y))

また、同じパラメーターでlist.sort()を試しました。ただし、いずれの場合でも、関数は引数としてリストを取得するのではなく、Noneを取得します。それがなぜなのか、私にはわからない。ほとんどがC++から来ているので、これは私のコールバック関数の考えと矛盾する。このリストをカスタム関数でソートするにはどうすればよいですか?

編集間違いを見つけました。元のリストを作成するチェーンでは、1つの関数は何も返さず、戻り値が使用されました。わざわざごめんなさい

49
DaClown
>>> l = [list(range(i, i+4)) for i in range(10,1,-1)]
>>> l
[[10, 11, 12, 13], [9, 10, 11, 12], [8, 9, 10, 11], [7, 8, 9, 10], [6, 7, 8, 9], [5, 6, 7, 8], [4, 5, 6, 7], [3, 4, 5, 6], [2, 3, 4, 5]]
>>> sorted(l, key=sum)
[[2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8], [6, 7, 8, 9], [7, 8, 9, 10], [8, 9, 10, 11], [9, 10, 11, 12], [10, 11, 12, 13]]

上記は機能します。別のことをしていますか?

キー関数はsumであることに注意してください。明示的に記述する必要はありません。

27
Katriel

また、比較関数が正しくありません。ブール値ではなく、-1、0、または1を返す必要があります。正しい比較関数は次のとおりです。

def compare(item1, item2):
    if fitness(item1) < fitness(item2):
        return -1
    Elif fitness(item1) > fitness(item2):
        return 1
    else:
        return 0
63
Michael Mouse

compare関数をわずかに変更し、functools.cmp_to_keyを使用してsortedに渡す必要があります。サンプルコード:

import functools

lst = [list(range(i, i+5)) for i in range(5, 1, -1)]

def fitness(item):
    return item[0]+item[1]+item[2]+item[3]+item[4]
def compare(item1, item2):
    return fitness(item1) - fitness(item2)

sorted(lst, key=functools.cmp_to_key(compare))

出力:

[[2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 8], [5, 6, 7, 8, 9]]

作品:)

13
JustAC0der

OPがカスタム比較関数の使用を求めていたので(そして、これがこの質問につながった理由でもあります)、ここでしっかりした答えをしたいと思います。

通常、カスタムコンパレータをパラメータとして使用する組み込みsorted()関数を使用します。 Python 3ではパラメーター名とセマンティクスが変更されたという事実に注意する必要があります。

カスタムコンパレーターの仕組み

カスタムコンパレータを提供する場合、通常、次のパターンに従う整数/浮動小数点値を返す必要があります(他のほとんどのプログラミング言語およびフレームワークと同様)。

  • 左の項目をソートする必要がある場合、負の値(_< 0_)を返しますbefore右の項目
  • 左の項目をソートする必要がある場合は正の値(_> 0_)を返します右の項目
  • 左と右の両方のアイテムの重量が同じであり、優先順位なしで「均等に」順序付けする必要がある場合は、_0_を返します

OPの質問の特定のケースでは、次のカスタム比較関数を使用できます。

_def compare(item1, item2):
    return fitness(item1) - fitness(item2)
_

マイナス操作の使用は、左のアイテム(ここでは_item1_)の重量が右のアイテム(ここでは_item2_)の重量よりも大きいときに正の値になるため、巧妙なトリックです。したがって、item1はitem2の後にソートされます。

ソート順を逆にする場合は、単純に減算を逆にします:return fitness(item2) - fitness(item1)

Python 2でsort()を呼び出す

_sorted(mylist, key=cmp(compare))
_

または:

_sorted(mylist, cmp=lambda item1, item2: fitness(item1) - fitness(item2))
_

Python 3でsort()を呼び出す

_from functools import cmp_to_key
sorted(mylist, key=cmp_to_key(compare))
_

または:

_from functools import cmp_to_key
sorted(mylist, key=cmp_to_key(lambda item1, item2: fitness(item1) - fitness(item2)))
_
1
Lars Blumberg