Python 3でカスタム比較関数を使用する方法


98

Python 2.xでは、私がソートされ、.sort関数にカスタム関数を渡すことができます

>>> x=['kar','htar','har','ar']
>>>
>>> sorted(x)
['ar', 'har', 'htar', 'kar']
>>> 
>>> sorted(x,cmp=customsort)
['kar', 'htar', 'har', 'ar']

で、ので私の言語、consonentsはこの順番が付属しています

"k","kh",....,"ht",..."h",...,"a"

しかし、Python 3.xではcmpキーワードを渡すことができなかったようです

>>> sorted(x,cmp=customsort)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'cmp' is an invalid keyword argument for this function

代替案はありますか、それとも自分でソートした関数も作成する必要がありますか?

注:「k」、「kh」などを使用して簡略化しました。実際の文字はUnicodeであり、さらに複雑です。子音の前後に母音がある場合があります。カスタム比較関数を実行したので、その部分は問題ありません。問題は、カスタム比較関数をソートまたは.sortに渡せなかったことです。


試しましたsorted(x)か?
SilentGhost

ので@SilentGhostは、作成してください、私は、もちろん、動作していないのは、もう一度試してみました私の元の言語の並べ替えを行うにオペレーションシステムにより、ロケールリストのサポートではありません。
YOU

1
キー関数としてcmpをラップできます。HowToSortingサイトでcmp_to_keyを検索します。
フランク・

これは似たようなものですstackoverflow.com/questions/49327344/…
Eziz Durdyyev

回答:


50

key引数を使用します(そして、古い関数を関数に変換する方法のレシピに従います)。cmpkey

functoolscmp_to_key言及されている機能がありますdocs.python.org/3.6/library/functools.html#functools.cmp_to_keyで


+1、レシピで回避策が得られたようですが< > = 、元のカスタムソートはCで書かれているため、すべての比較演算子を中間者に渡すと、パフォーマンスがいくらか失われると思います。デフォルトのソート。
YOU

2
(あなたのプロフィールを見ただけです)あなたの会社はGoogleとStackOverflowへのアクセスをブロックしていますか?彼らはどれほど愚かなことができますか?しかし、あなたの反応について:実際のパフォーマンスの低下に興味があります。できますtimeitか?
Tim Pietzcker

4
いくつかのベンチマークを実行しましたが、カスタムC比較関数を直接渡すよりも約4倍遅くなります。
YOU

2
key関数とcmp関数の両方が必要な場合はどうなりますか?各辞書のカスタムキーで辞書のリストを並べ替えたいのですが。sorted_rows = sorted(rows, key=itemgetter('name'), cmp=locale.strxfrm)TypeError: 'cmp'はPython 3.2ではこの関数の無効なキーワード引数です:(
bitek

4
functoolsは、標準ライブラリにcmp_to_key機能を持っていますdocs.python.org/3.6/library/functools.html
マルティンFixman


17

customsort()の代わりに、各単語をPythonがソート方法をすでに知っているものに変換する関数が必要です。たとえば、各単語を数字のリストに変換できます。各数字は、アルファベットの各文字が出現する場所を表します。このようなもの:

my_alphabet = ['a', 'b', 'c']

def custom_key(word):
   numbers = []
   for letter in word:
      numbers.append(my_alphabet.index(letter))
   return numbers

x=['cbaba', 'ababa', 'bbaa']
x.sort(key=custom_key)

言語には複数文字の文字が含まれているため、custom_key関数は明らかにより複雑にする必要があります。しかし、それはあなたに一般的な考えを与えるはずです。


ありがとう+1、それはICUの考え方だと思います。しかし、私の言語には単語区切りがなく、標準のローマ字規則もないので、研究には時間がかかると思います。
YOU

9

完全なpython3 cmp_to_keyラムダの例:

from functools import cmp_to_key

nums = [28, 50, 17, 12, 121]
nums.sort(key=cmp_to_key(lambda x, y: 1 if str(x)+str(y) < str(y)+str(x) else -1))

一般的なオブジェクトの並べ替えと比較します。

class NumStr:
    def __init__(self, v):
        self.v = v
    def __lt__(self, other):
        return self.v + other.v < other.v + self.v


A = [NumStr("12"), NumStr("121")]
A.sort()
print(A[0].v, A[1].v)

A = [obj.v for obj in A]
print(A)

4

これで効果があるかどうかはわかりませんが、localeモジュールを確認してください。ロケールを言語に設定locale.strcollし、言語の並べ替えルールを使用して文字列を比較するために使用できるようです。


これは人気のある言語に当てはまりますが、私の言語はオペレーションシステム、ICU、unicode.orgで完全にはサポートされていないため、問題はありませんが、+ 1をお勧めします。
YOU

-2

key代わりに引数を使用してください。これは、処理中の値を取り、並べ替えに使用するキーを提供する単一の値を返す関数を取ります。

sorted(x, key=somekeyfunc)

3
キーは1つのパラメーター関数のみを受け入れます。cmpには2つのパラメーターがあり、それらは異なる動作です。そして私は、唯一つのパラメータを渡すための鍵キーワードの、だエラー、テストTypeError: customsort() takes exactly 2 positional arguments (1 given)
YOU
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.