Python 3'te özel bir karşılaştırma işlevi nasıl kullanılır?


98

In Python 2.x , ben sıralanır ve .sort fonksiyonlara özel işlev geçebileceği

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

Çünkü benim dilimde ünsüzler bu sırayla gelir

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

Ancak Python 3.x'te , cmpanahtar kelimeyi geçemedim gibi görünüyor

>>> 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

Herhangi bir alternatif var mı yoksa kendi sıralanmış işlevimi de yazmalı mıyım?

Not: "k", "kh", vb. Kullanarak basitleştirdim. Gerçek karakterler Unicodes ve daha da karmaşık, bazen ünlüler ünsüzlerden önce ve sonra geliyor, özel karşılaştırma işlevi yaptım, Yani bu kısım tamam. Tek sorun, özel karşılaştırma işlevimi sıralı veya .sort olarak geçiremememdir.


sadece denedin sorted(x)mi
SilentGhost

Çünkü @SilentGhost, yapmak için emin, ben sadece, ders çalışmıyor ki, tekrar denedi benim orijinal dili sıralama yapmak Operasyon Systems tarafından yerel liste destek değildir.
SİZ

1
Cmp'nizi bir anahtar işlev olarak kaydırabilirsiniz. HowToSorting sitesinde cmp_to_key için arama yapın.
Frank

Yanıtlar:


50

keyArgümanı kullanın (ve eski işlevinizi bir işleve nasıl dönüştüreceğinizin tarifini izleyin ).cmpkey

functoolsdocs.python.org/3.6/library/functools.html#functools.cmp_to_keycmp_to_key adresinde bahsedilen bir işleve sahiptir


+1, tarif bana bir geçici çözüm veriyor gibi görünüyor, ancak tüm karşılaştırma işleçlerini < > = orta adama geçirerek biraz performans kaybedeceğimi düşünüyorum , çünkü orijinal özel sıralamam C ile yazıldığından, yaklaşık 1 / 2x hıza sahipti. varsayılan sıralama.
SİZ

2
(Sadece profilinize baktım) Şirketiniz Google ve StackOverflow'a erişimi engelliyor mu? Ne kadar aptal olabilirler? Ancak cevabınız hakkında: Gerçek performans düşüşüyle ​​ilgilenirim. Yapabilir misin timeit?
Tim Pietzcker

4
Bazı kriterler yaptım, özel C karşılaştırma işlevini doğrudan geçmekten yaklaşık 4 kat daha yavaş görünüyor.
SİZ

2
Ya hem bir anahtar işleve hem de bir cmp işlevine ihtiyacım olursa? Her sözlükte özel bir anahtara göre bir sözlük listesini sıralamak istiyorum. sorted_rows = sorted(rows, key=itemgetter('name'), cmp=locale.strxfrm)TypeError verir: 'cmp' bu işlev için geçersiz bir anahtar kelime argümanıdır, Python 3.2'de :(
bitek

4
functools, standart kitaplıkta bir cmp_to_key işlevine sahiptir: docs.python.org/3.6/library/functools.html
Martín

59

Kullanım keyanahtar kelime ve functools.cmp_to_key senin karşılaştırma işlevi dönüştürmek için:

sorted(x, key=functools.cmp_to_key(customsort))

17

Customsort () yerine, her kelimeyi Python'un nasıl sıralayacağını bildiği bir şeye çeviren bir işleve ihtiyacınız var. Örneğin, her kelimeyi alfabenizde her harfin geçtiği yeri temsil ettiği sayılar listesine çevirebilirsiniz. Bunun gibi bir şey:

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)

Diliniz çok karakterli harfler içerdiğinden, custom_key işlevinizin açıkça daha karmaşık olması gerekecektir. Bu size genel bir fikir vermeli.


Teşekkürler +1, Bence bu yoğun bakım yolu. ama benim dilimde kelime ayırıcılar olmadığından ve standart Latin alfabesi kuralları olmadığından araştırma yapmak zaman alacaktır diye düşünüyorum.
SİZ

9

Tam bir python3 cmp_to_key lambda örneği:

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))

yaygın nesne sıralamasıyla karşılaştırın:

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

Bunun yardımcı olup olmayacağını bilmiyorum, ancak localemodülü kontrol edebilirsiniz . Görünüşe göre yerel ayarı kendi dilinize ayarlayabilir ve locale.strcolldilinizin sıralama kurallarını kullanarak dizeleri karşılaştırmak için kullanabilirsiniz .


Bu popüler diller için doğrudur ancak benim dilim İşletim Sistemleri, ICU ve unicode.org tarafından tam olarak desteklenmemektedir, bu nedenle bu söz konusu değildir, ancak iyi bir öneri için +1.
SİZ

-2

Kullanım keyyerine argüman. İşlenmekte olan değeri alan ve anahtarın sıralama için kullanması için tek bir değer döndüren bir işlevi alır.

sorted(x, key=somekeyfunc)

3
anahtar yalnızca bir parametre işlevini kabul eder, cmp'nin 2 parametresi vardır, bunlar farklı davranışlardır. ve az önce test ettim, hata aldım, çünkü anahtar anahtar kelime yalnızca bir parametreyi geçiyorTypeError: customsort() takes exactly 2 positional arguments (1 given)
YOU
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.