Aku ingin menulis cmp
fungsi -seperti yang membandingkan dua nomor versi dan kembali -1
, 0
atau 1
berdasarkan valuses mereka dibandingkan.
- Kembalikan
-1
jika versi A lebih lama dari versi B - Kembalikan
0
jika versi A dan B setara - Kembalikan
1
jika versi A lebih baru dari versi B
Setiap sub-bagian seharusnya ditafsirkan sebagai angka, oleh karena itu 1,10> 1,1.
Keluaran fungsi yang diinginkan adalah
mycmp('1.0', '1') == 0
mycmp('1.0.0', '1') == 0
mycmp('1', '1.0.0.1') == -1
mycmp('12.10', '11.0.0.0.0') == 1
...
Dan inilah implementasi saya, terbuka untuk perbaikan:
def mycmp(version1, version2):
parts1 = [int(x) for x in version1.split('.')]
parts2 = [int(x) for x in version2.split('.')]
# fill up the shorter version with zeros ...
lendiff = len(parts1) - len(parts2)
if lendiff > 0:
parts2.extend([0] * lendiff)
elif lendiff < 0:
parts1.extend([0] * (-lendiff))
for i, p in enumerate(parts1):
ret = cmp(p, parts2[i])
if ret: return ret
return 0
Saya menggunakan Python 2.4.5 btw. (dipasang di tempat kerja saya ...).
Berikut adalah 'rangkaian pengujian' kecil yang dapat Anda gunakan
assert mycmp('1', '2') == -1
assert mycmp('2', '1') == 1
assert mycmp('1', '1') == 0
assert mycmp('1.0', '1') == 0
assert mycmp('1', '1.000') == 0
assert mycmp('12.01', '12.1') == 0
assert mycmp('13.0.1', '13.00.02') == -1
assert mycmp('1.1.1.1', '1.1.1.1') == 0
assert mycmp('1.1.1.2', '1.1.1.1') == 1
assert mycmp('1.1.3', '1.1.3.000') == 0
assert mycmp('3.1.1.0', '3.1.2.10') == -1
assert mycmp('1.1', '1.10') == -1
python
string-comparison
Johannes Charra
sumber
sumber
Jawaban:
Hapus bagian string yang tidak menarik (nol dan titik di belakangnya), lalu bandingkan daftar angka.
Ini adalah pendekatan yang sama dengan Pär Wieslander, tetapi sedikit lebih ringkas:
Berikut adalah beberapa pengujian, berkat " Bagaimana cara membandingkan dua string dalam format versi yang dipisahkan titik di Bash? ":
sumber
rstrip(".0")
akan mengubah ".10" menjadi ".1" di "1.0.10".Bagaimana kalau menggunakan Python
distutils.version.StrictVersion
?Jadi untuk
cmp
fungsi Anda :Jika Anda ingin membandingkan nomor versi yang lebih kompleks
distutils.version.LooseVersion
akan lebih berguna, namun pastikan untuk hanya membandingkan jenis yang sama.LooseVersion
bukanlah alat yang paling cerdas, dan dapat dengan mudah diakali:Untuk sukses dengan trah ini, Anda harus keluar dari perpustakaan standar dan menggunakan utilitas parsing setuptools
parse_version
.Jadi tergantung pada kasus penggunaan spesifik Anda, Anda harus memutuskan apakah
distutils
alat bawaan sudah cukup, atau jika dijamin untuk ditambahkan sebagai ketergantungansetuptools
.sumber
StrictVersion
HANYA berfungsi hingga versi tiga nomor. Gagal untuk hal-hal seperti0.4.3.6
!distribute
dalam jawaban ini harus diganti dengansetuptools
, yang disertakan bersamapkg_resources
paket dan sejak ... seperti, selamanya . Demikian juga, ini adalah dokumentasi resmi untukpkg_resources.parse_version()
fungsi yang disertakansetuptools
.Apakah penggunaan kembali dianggap elegan dalam hal ini? :)
sumber
pkg_resources
adalahsetuptools
paket -bundled. Karenasetuptools
secara efektif wajib pada semua instalasi Python,pkg_resources
tersedia secara efektif di mana-mana.distutils.version
Meskipun demikian , subpaket juga berguna - meskipun kurang cerdas dibandingkanpkg_resources.parse_version()
fungsi tingkat yang lebih tinggi . Yang harus Anda manfaatkan tergantung pada tingkat kegilaan yang Anda harapkan dalam string versi.setuptools
berada di luar perpustakaan standar, dan sebaliknya dengan preferensi yang saya nyatakandistutils
dalam kasus ini . Jadi apa sebenarnya yang Anda maksud dengan "wajib secara efektif", dan tolong dapatkah Anda memberikan bukti bahwa itu "wajib secara efektif" 4,5 tahun yang lalu ketika saya menulis komentar ini?Tidak perlu mengulangi tupel versi. Operator perbandingan bawaan pada list dan tuple sudah berfungsi persis seperti yang Anda inginkan. Anda hanya perlu menambah daftar versi ke nol sesuai panjangnya. Dengan python 2.6 Anda dapat menggunakan izip_longest untuk mengisi urutan.
Dengan versi yang lebih rendah, beberapa peretasan peta diperlukan.
sumber
Ini sedikit lebih ringkas dari saran Anda. Alih-alih mengisi versi yang lebih pendek dengan nol, saya menghapus nol yang tertinggal dari daftar versi setelah memisahkan.
sumber
mycmp
untuk tujuan lain dalam kode Anda jika Anda membutuhkannya.Hapus trailing
.0
dan.00
dengan regex,split
dan gunakancmp
fungsi yang membandingkan array dengan benar:Dan, tentu saja, Anda dapat mengubahnya menjadi satu baris jika Anda tidak keberatan dengan antrean yang panjang.
sumber
Ini satu liner (terbagi untuk keterbacaan). Tidak yakin tentang yang dapat dibaca ...
sumber
tuple
tidak diperlukan btw):cmp(*zip(*map(lambda x,y:(x or 0,y or 0), map(int,v1.split('.')), map(int,v2.split('.')) )))
Implementasikan untuk php
version_compare
, kecuali "=". Karena itu ambigu.sumber
Daftar dapat dibandingkan dengan Python, jadi jika seseorang mengonversi string yang mewakili angka menjadi bilangan bulat, perbandingan Python dasar dapat digunakan dengan sukses.
Saya perlu memperluas pendekatan ini sedikit karena saya menggunakan Python3x di mana
cmp
fungsinya sudah tidak ada lagi. Saya harus menirucmp(a,b)
dengan(a > b) - (a < b)
. Dan, nomor versi sama sekali tidak bersih, dan dapat berisi semua jenis karakter alfanumerik lainnya. Ada beberapa kasus ketika fungsi tidak dapat memberi tahu pesanan sehingga ia kembaliFalse
(lihat contoh pertama).Jadi saya memposting ini meskipun pertanyaannya sudah lama dan sudah dijawab, karena mungkin menghemat beberapa menit dalam kehidupan seseorang.
sumber
Jika Anda tidak ingin menarik ketergantungan eksternal di sini adalah upaya saya yang ditulis untuk Python 3.x.
rc
,rel
(dan mungkin bisa ditambahkanc
) dianggap sebagai "kandidat rilis" dan membagi nomor versi menjadi dua bagian dan jika hilang, nilai bagian kedua tinggi (999). Huruf lain menghasilkan perpecahan dan dibagikan sebagai sub-angka melalui kode basis-36.sumber
Solusi yang paling sulit untuk dibaca, tetapi tetap satu baris! dan menggunakan iterator agar cepat.
itu untuk Python2.6 dan 3. + btw, Python 2.5 dan yang lebih tua perlu menangkap StopIteration.
sumber
Saya melakukan ini untuk dapat mengurai dan membandingkan string versi paket Debian. Harap perhatikan bahwa itu tidak ketat dengan validasi karakter.
Ini mungkin berguna juga:
sumber
Solusi lain:
Seseorang juga dapat menggunakan seperti ini:
sumber
Saya menggunakan yang ini di proyek saya:
sumber
Bertahun-tahun kemudian, tetapi pertanyaan ini masih ada di atas.
Ini adalah fungsi sortir versi saya. Ini membagi versi menjadi bagian angka dan non-angka. Angka dibandingkan sebagai
int
sisastr
(sebagai bagian dari item daftar).Anda dapat menggunakan fungsi
key
sebagai tipe kustomVersion
dengan operator pembanding. Jika benar-benar ingin menggunakancmp
Anda dapat melakukannya seperti di contoh ini: https://stackoverflow.com/a/22490617/9935708Lulus uji suite.
sumber
Solusi pilihan saya:
Mengisi string dengan nol ekstra dan hanya menggunakan empat angka nol terlebih dahulu mudah dipahami, tidak memerlukan regex apa pun, dan lambda lebih atau kurang dapat dibaca. Saya menggunakan dua baris agar mudah dibaca, bagi saya keanggunan itu pendek dan sederhana.
sumber
Ini solusi saya (ditulis dalam C, maaf). Saya harap Anda akan merasakan manfaatnya
sumber