Saya membutuhkan fungsi berikut:
Input : alist
Keluaran :
True
jika semua elemen dalam daftar input mengevaluasi sama satu sama lain menggunakan operator kesetaraan standar;False
jika tidak.
Kinerja : tentu saja, saya lebih suka untuk tidak mengeluarkan biaya tidak perlu.
Saya merasa akan lebih baik untuk:
- beralih melalui daftar
- membandingkan elemen yang berdekatan
- dan
AND
semua nilai Boolean yang dihasilkan
Tapi saya tidak yakin apa cara paling Pythonic untuk melakukan itu.
Kurangnya fitur hubung singkat hanya menyakitkan pada input panjang (lebih dari ~ 50 elemen) yang memiliki elemen yang tidak sama sejak awal. Jika ini terjadi cukup sering (seberapa sering tergantung pada berapa lama daftar mungkin), korsleting diperlukan. Algoritme korsleting terbaik tampaknya adalah @ KennyTM checkEqual1
. Namun, membayar biaya yang signifikan untuk ini:
- hingga 20x dalam daftar kinerja hampir identik
- kinerja hingga 2,5x pada daftar pendek
Jika input panjang dengan elemen awal yang tidak sama tidak terjadi (atau jarang terjadi), korsleting tidak diperlukan. Kemudian, sejauh ini yang tercepat adalah solusi @Ivo van der Wijk.
sumber
a == b
atau identik dengan dia is b
?functools.reduce(operator.eq, a)
belum disarankan.Jawaban:
Metode umum:
Satu-liner:
Juga satu-liner:
Perbedaan antara 3 versi adalah:
checkEqual2
konten harus hashable.checkEqual1
dancheckEqual2
dapat menggunakan iterator apa pun, tetapicheckEqual3
harus mengambil input berurutan, biasanya wadah beton seperti daftar atau tupel.checkEqual1
berhenti segera setelah perbedaan ditemukan.checkEqual1
mengandung lebih banyak kode Python, itu kurang efisien ketika banyak item sama di awal.checkEqual2
dancheckEqual3
selalu melakukan operasi penyalinan O (N), itu akan memakan waktu lebih lama jika sebagian besar input Anda akan mengembalikan False.checkEqual2
dancheckEqual3
lebih sulit untuk menyesuaikan perbandingan daria == b
kea is b
.timeit
hasil, untuk Python 2.7 dan (hanya s1, s4, s7, s9 harus mengembalikan True)kita mendapatkan
catatan:
sumber
obj.__eq__
saatlhs is rhs
, dan optimisasi out-of-order untuk memungkinkan daftar diurutkan hubungan pendek lebih cepat.itertools
resep yang saya tambahkan sebagai jawaban. Mungkin ada baiknya melemparkan itu ke dalam matriks waktu Anda :-).Solusi yang lebih cepat daripada menggunakan set () yang bekerja pada urutan (bukan iterables) adalah cukup menghitung elemen pertama. Ini mengasumsikan bahwa daftar ini tidak kosong (tapi itu sepele untuk diperiksa, dan tentukan sendiri apa hasilnya di daftar kosong)
beberapa tolok ukur sederhana:
sumber
x.count(next(x)) == len(x)
sehingga berfungsi untuk setiap wadah x? Ahh .. nm, baru saja melihat .count hanya tersedia untuk sekuens .. Mengapa tidak diterapkan untuk wadah bawaan lainnya? Apakah menghitung di dalam kamus secara inheren kurang berarti daripada di dalam daftar?count
tidak diterapkan untuk iterables, bukan mengapalen
tidak tersedia untuk iterators. Jawabannya mungkin itu hanya kekhilafan. Tapi itu tidak relevan bagi kami karena standar.count()
untuk urutan sangat lambat (python murni). Alasan solusi Anda begitu cepat adalah bahwa itu bergantung pada C-diimplementasikan yangcount
disediakan olehlist
. Jadi saya kira mana saja yang terjadi untuk menerapkancount
metode dalam C akan mendapat manfaat dari pendekatan Anda.Cara paling sederhana dan paling elegan adalah sebagai berikut:
(Ya, ini bahkan berfungsi dengan daftar kosong! Ini karena ini adalah salah satu dari sedikit kasus di mana python memiliki semantik malas.)
Mengenai kinerja, ini akan gagal sedini mungkin, sehingga asimtotik optimal.
sumber
checkEqual1
. Saya tidak yakin mengapa.first=myList[0]
all(x==first for x in myList)
, mungkinfirst=myList[0]
akan melemparIndexError
pada daftar kosong, jadi komentator yang berbicara tentang optimasi yang saya sebutkan harus berurusan dengan kasus tepi dari daftar kosong. Namun yang asli baik-baik saja (baikx==myList[0]
-baik saja di dalamall
karena tidak pernah dievaluasi jika daftar kosong).Pekerjaan perbandingan yang ditetapkan:
Menggunakan
set
menghapus semua elemen duplikat.sumber
Anda dapat mengubah daftar menjadi satu set. Satu set tidak dapat memiliki duplikat. Jadi jika semua elemen dalam daftar asli identik, set akan memiliki hanya satu elemen.
sumber
len(set(input_list)) == 1
?Untuk apa nilainya, ini muncul di milis python-ideas baru-baru ini. Ternyata sudah ada resep itertools untuk melakukan ini: 1
Seharusnya berkinerja sangat baik dan memiliki beberapa properti bagus.
1 Dengan kata lain, saya tidak dapat mengambil kredit untuk datang dengan solusi - saya juga tidak dapat mengambil kredit untuk bahkan menemukannya .
sumber
return next(g, f := next(g, g)) == f
(dari py3.8 tentu saja)Berikut adalah dua cara sederhana untuk melakukan ini
menggunakan set ()
Saat mengonversi daftar ke set, elemen duplikat dihapus. Jadi jika panjang himpunan dikonversi adalah 1, maka ini berarti bahwa semua elemen adalah sama.
Berikut ini sebuah contoh
menggunakan semua ()
Ini akan membandingkan (ekivalensi) elemen pertama dari daftar input dengan setiap elemen lain dalam daftar. Jika semua yang ekuivalen Benar akan dikembalikan, jika tidak Palsu akan dikembalikan.
Berikut ini sebuah contoh
PS Jika Anda memeriksa untuk melihat apakah seluruh daftar setara dengan nilai tertentu, Anda dapat suibstitue nilai dalam untuk input_list [0].
sumber
len(set(a))
pada daftar 10.000.000 elemen membutuhkan waktu 0,09 detik sedangkan performaall
membutuhkan waktu 0,9 detik (10 kali lebih lama).Ini adalah pilihan lain, lebih cepat daripada
len(set(x))==1
daftar panjang (menggunakan hubungan pendek)sumber
Ini adalah cara sederhana untuk melakukannya:
Ini sedikit lebih rumit, itu mengeluarkan fungsi panggilan overhead, tetapi semantik lebih jelas dijabarkan:
sumber
for elem in mylist[1:]
. Keraguan itu meningkatkan kecepatan jauh karena saya kiraelem[0] is elem[0]
sehingga penerjemah mungkin dapat melakukan perbandingan itu dengan sangat cepat.Periksa apakah semua elemen sama dengan yang pertama.
np.allclose(array, array[0])
sumber
Keraguan ini adalah "yang paling Pythonic", tetapi sesuatu seperti:
akan melakukan trik.
sumber
for
Lingkaran Anda dapat dibuat menjadi lebih Pythonicif any(item != list[0] for item in list[1:]): return False
, dengan semantik yang persis sama.Jika Anda tertarik pada sesuatu yang sedikit lebih mudah dibaca (tapi tentu saja tidak seefisien,) Anda dapat mencoba:
sumber
Ubah daftar menjadi himpunan dan kemudian temukan jumlah elemen dalam himpunan. Jika hasilnya 1, memiliki elemen identik dan jika tidak, maka elemen dalam daftar tidak identik.
sumber
Mengenai menggunakan
reduce()
denganlambda
. Berikut adalah kode kerja yang menurut saya pribadi jauh lebih baik daripada beberapa jawaban lainnya.Mengembalikan tuple di mana nilai pertama adalah boolean jika semua item sama atau tidak.
sumber
[1, 2, 2]
): tidak memperhitungkan nilai boolean sebelumnya. Ini dapat diperbaiki dengan menggantix[1] == y
denganx[0] and x[1] == y
.Saya akan melakukan:
sebagai
any
berhenti mencari iterable secepat itu menemukanTrue
kondisi.sumber
all()
, mengapa tidak digunakanall(x == seq[0] for x in seq)
? terlihat lebih pythonic dan harus melakukan hal yang samasumber
Bekerja di Python 2.4, yang tidak memiliki "semua".
sumber
for k in j: break
setara dengannext(j)
. Anda juga bisa melakukannyadef allTheSame(x): return len(list(itertools.groupby(x))<2)
jika Anda tidak peduli dengan efisiensi.Dapat menggunakan peta dan lambda
sumber
Atau gunakan
diff
metode numpy:Dan untuk menelepon:
Keluaran:
sumber
not np.any(np.diff(l))
bisa sedikit lebih cepat.Atau gunakan metode beda numpy:
Dan untuk menelepon:
Keluaran:
Benar
sumber
Anda dapat melakukan:
Agak menyebalkan bahwa python membuat Anda mengimpor seperti operator
operator.and_
. Pada python3, Anda juga harus mengimporfunctools.reduce
.(Anda tidak boleh menggunakan metode ini karena tidak akan rusak jika menemukan nilai yang tidak sama, tetapi akan terus memeriksa seluruh daftar. Itu hanya dimasukkan di sini sebagai jawaban untuk kelengkapan.)
sumber
Yang berikutnya akan mengalami hubungan pendek:
sumber
reduce(lambda a,b:a==b, [2,2,2])
menghasilkanFalse
... Saya mengeditnya, tetapi cara ini tidak cantik lagiUbah daftar menjadi satu set. Kemudian jika ukuran set hanya 1, mereka pasti sama.
sumber
Ada juga opsi rekursif Python murni:
Namun untuk beberapa alasan, dalam beberapa kasus dua urutan besarnya lebih lambat dari opsi lain. Berasal dari mentalitas bahasa C, saya mengharapkan ini lebih cepat, tetapi ternyata tidak!
Kerugian lainnya adalah bahwa ada batas rekursi dalam Python yang perlu disesuaikan dalam kasus ini. Misalnya menggunakan ini .
sumber
Anda dapat menggunakan
.nunique()
untuk menemukan sejumlah item unik dalam daftar.sumber
Anda dapat menggunakan
set
. Ini akan membuat set dan menghapus elemen berulang. Kemudian periksa apakah ia memiliki tidak lebih dari 1 elemen.Contoh:
sumber