pengurutan daftar case-insensitive, tanpa menurunkan hasil?


133

Saya punya daftar string seperti ini:

['Aden', 'abel']

Saya ingin menyortir item, tidak sensitif huruf besar / kecil. Jadi saya ingin mendapatkan:

['abel', 'Aden']

Tapi saya kebalikannya dengan sorted()atau list.sort(), karena huruf besar muncul sebelum huruf kecil.

Bagaimana saya bisa mengabaikan kasus ini? Saya telah melihat solusi yang melibatkan lebih rendah semua item daftar, tetapi saya tidak ingin mengubah kasus item daftar.


Jawaban:


192

Di Python 3.3+ ada str.casefoldmetode yang dirancang khusus untuk pencocokan tanpa casing:

sorted_list = sorted(unsorted_list, key=str.casefold)

Dalam Python 2 gunakan lower():

sorted_list = sorted(unsorted_list, key=lambda s: s.lower())

Ini berfungsi untuk string normal dan unicode, karena keduanya memiliki lowermetode.

Dalam Python 2 ini berfungsi untuk campuran string normal dan unicode, karena nilai kedua tipe dapat dibandingkan satu sama lain. Namun, Python 3 tidak berfungsi seperti itu: Anda tidak dapat membandingkan string byte dan string unicode, jadi dalam Python 3 Anda harus melakukan hal yang waras dan hanya mengurutkan daftar satu jenis string.

>>> lst = ['Aden', u'abe1']
>>> sorted(lst)
['Aden', u'abe1']
>>> sorted(lst, key=lambda s: s.lower())
[u'abe1', 'Aden']

11
Satu dapat menghindari fungsi lambda pulang pergi dengan (Python 3) menggunakan str.lowerfungsi umum sebagai sorted(lst, key=str.lower)atau (Python 2) menggunakan lowermetode stringmodul sebagai sorted(lst, key=string.lower). Satu juga dapat digunakan str.loweruntuk string dalam Python 2, tetapi kemudian harus digunakan unicode.loweruntuk unicodeobjek, sedangkan string.lowermenerima keduanya (yang, seperti yang Anda katakan, mungkin bukan benar-benar mode operasi "waras", meskipun).
Daniel Andersson

Ini tidak akan berfungsi untuk daftar seperti ['Z', 'B', 'a', 'b', 'A'], yang mirip dengan ['a', 'A', 'B', 'B', 'b', 'Z']. Huruf kapital 'B' muncul di depan huruf kecil 'b' karena sort Python () dan sortir () mempertahankan urutan asli ketika string cocok. Dalam hal ini, modal 'B' dianggap cocok dengan huruf kecil 'b' saat menggunakan casefold. Ini selalu terjadi jika Anda mengonversi case untuk membandingkan: diurutkan (spam, key = str.lower) atau diurutkan (spam, key = str.upper) atau diurutkan (spam, key = str.casefold).
PJ Singh

Coba solusi ini sebagai gantinya: stackoverflow.com/a/1098160/10668287 . Ini akan mengurutkan ['Aden', 'aden'] dengan benar sebagai ['aden', 'Aden'].
PJ Singh

46
>>> x = ['Aden', 'abel']
>>> sorted(x, key=str.lower) # Or unicode.lower if all items are unicode
['abel', 'Aden']

Dalam Python 3 stradalah unicode tetapi dalam Python 2 Anda dapat menggunakan pendekatan yang lebih umum ini yang berfungsi untuk keduanya strdan unicode:

>>> sorted(x, key=lambda s: s.lower())
['abel', 'Aden']

Terima kasih. Saya tahu saya seharusnya menyebutkan ini sebelumnya, tapi saya pernah mendengar ada masalah dengan menggunakan metode ini pada string unicode (Py2). Apakah Anda tahu sesuatu tentang itu?

Semuanya unicode. Terima kasih! Satu pertanyaan lagi, bagaimana melakukannya pada daftar seperti ini:[['Aden'], ['abel']]

Apakah setiap daftar hanya memiliki satu item? Jika demikian, modifikasi sedikit ke:sorted(x,key=lambda i:i[0].lower())
jamylak

Yah, mungkin ada beberapa hal lain juga, yang seharusnya tidak digunakan untuk menyortir.

1
Tidak masalah, sepertinya saya salah, penyortiran tidak berfungsi untuk campuran string dan unicode, saya bingung dengan pertanyaan sebelumnya di mana tuple juga termasuk dalam pengurutan.
jamylak

10

Anda juga dapat mencoba ini untuk mengurutkan daftar di tempat:

>>> x = ['Aden', 'abel']
>>> x.sort(key=lambda y: y.lower())
>>> x
['abel', 'Aden']


3

Di python3 Anda bisa menggunakan

list1.sort(key=lambda x: x.lower()) #Case In-sensitive             
list1.sort() #Case Sensitive

1

Saya melakukannya dengan cara ini untuk Python 3.3:

 def sortCaseIns(lst):
    lst2 = [[x for x in range(0, 2)] for y in range(0, len(lst))]
    for i in range(0, len(lst)):
        lst2[i][0] = lst[i].lower()
        lst2[i][1] = lst[i]
    lst2.sort()
    for i in range(0, len(lst)):
        lst[i] = lst2[i][1]

Maka Anda bisa memanggil fungsi ini:

sortCaseIns(yourListToSort)

0

Jenis case-insensitive, menyortir string pada tempatnya , dengan Python 2 OR 3 (diuji dengan Python 2.7.17 dan Python 3.6.9):

>>> x = ["aa", "A", "bb", "B", "cc", "C"]
>>> x.sort()
>>> x
['A', 'B', 'C', 'aa', 'bb', 'cc']
>>> x.sort(key=str.lower)           # <===== there it is!
>>> x
['A', 'aa', 'B', 'bb', 'C', 'cc']

Kuncinya adalah key=str.lower. Inilah yang terlihat dari perintah-perintah itu hanya dengan perintah, untuk memudahkan penyalinan sehingga Anda dapat mengujinya:

x = ["aa", "A", "bb", "B", "cc", "C"]
x.sort()
x
x.sort(key=str.lower)
x

Perhatikan bahwa jika string Anda adalah string unicode, (seperti u'some string'), maka hanya dalam Python 2 (BUKAN dalam Python 3 dalam kasus ini) x.sort(key=str.lower)perintah di atas akan gagal dan menghasilkan kesalahan berikut:

TypeError: descriptor 'lower' requires a 'str' object but received a 'unicode'

Jika Anda mendapatkan kesalahan ini, maka tingkatkan ke Python 3 di mana mereka menangani penyortiran unicode, atau mengonversi string unicode Anda menjadi string ASCII terlebih dahulu, menggunakan pemahaman daftar, seperti ini:

# for Python2, ensure all elements are ASCII (NOT unicode) strings first
x = [str(element) for element in x]  
# for Python2, this sort will only work on ASCII (NOT unicode) strings
x.sort(key=str.lower)

Referensi:

  1. https://docs.python.org/3/library/stdtypes.html#list.sort
  2. Ubah string Unicode menjadi string dengan Python (berisi simbol tambahan)
  3. https://www.programiz.com/python-programming/list-comprehension

-3

Coba ini

def cSort(inlist, minisort=True):
    sortlist = []
    newlist = []
    sortdict = {}
    for entry in inlist:
        try:
            lentry = entry.lower()
        except AttributeError:
            sortlist.append(lentry)
        else:
            try:
                sortdict[lentry].append(entry)
            except KeyError:
                sortdict[lentry] = [entry]
                sortlist.append(lentry)

    sortlist.sort()
    for entry in sortlist:
        try:
            thislist = sortdict[entry]
            if minisort: thislist.sort()
            newlist = newlist + thislist
        except KeyError:
            newlist.append(entry)
    return newlist

lst = ['Aden', 'abel']
print cSort(lst)

Keluaran

['abel', 'Aden']


9
Solusi ini berlebihan dan tidak dapat dibaca ketika satu liner sudah mencukupi. Ini mungkin lebih dapat diterima dalam bahasa selain Python.
IceArdor
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.