Saya mencoba untuk mengevaluasi ((x == a and y == b) or (x == b and y == a))
dengan Python, tetapi sepertinya agak bertele-tele. Apakah ada cara yang lebih elegan?
python
boolean-logic
LetEpsilonBeLessThanZero
sumber
sumber
x,y, a,b
: apakah int / float / string, objek arbitrer, atau apa? Jika mereka adalah tipe builtin dan dimungkinkan untuk menjaga keduanyax,y
dana,b
dalam urutan, maka Anda dapat menghindari cabang kedua. Perhatikan bahwa membuat himpunan akan menyebabkan masing-masing dari empat elemenx,y, a,b
menjadi hash, yang mungkin atau mungkin tidak sepele atau memiliki implikasi kinerja tergantung sepenuhnya pada jenis objek apa mereka.((x == a and y == b) or (x == b and y == a))
mungkin terlihat yukky, tetapi 1) maksudnya sangat jelas dan dapat dipahami oleh semua programmer non-Python, tidak samar 2) interpreter / kompiler akan selalu menanganinya dengan baik dan pada dasarnya tidak pernah dapat menghasilkan kode non-performant, tidak seperti alternatif. Jadi, 'lebih elegan' juga dapat memiliki kelemahan serius.Jawaban:
Jika elemen hashable, Anda bisa menggunakan set:
sumber
{1, 1, 2} == {1, 2, 2}
. Pada titik itu, Anda perlusorted
atauCounter
.Saya pikir yang terbaik yang bisa Anda dapatkan adalah mengemasnya menjadi tupel:
Atau, mungkin membungkusnya dalam satu set pencarian
Hanya karena disebutkan oleh beberapa komentar, saya melakukan beberapa pengaturan waktu, dan tupel dan set muncul untuk tampil secara identik di sini ketika pencarian gagal:
Meskipun tuple sebenarnya lebih cepat ketika pencarian berhasil:
Saya memilih untuk menggunakan set karena saya sedang melakukan pencarian keanggotaan, dan secara konseptual satu set lebih cocok untuk case-use daripada tuple. Jika Anda mengukur perbedaan yang signifikan antara kedua struktur dalam use case tertentu, gunakan yang lebih cepat. Saya tidak berpikir kinerja adalah faktor di sini.
sumber
if (a, b) in ((x, y), (y, x))
?set
solusi dalam jawaban untuk solusi tuple dari @Brilliand?Tuples membuatnya sedikit lebih mudah dibaca:
Ini memberikan petunjuk: kami memeriksa apakah urutannya
x, y
sama dengan urutannyaa, b
tetapi mengabaikan pemesanan. Itu hanya menetapkan kesetaraan!sumber
,
membuat tuple, bukan daftar. begitu(x, y)
dan(a, b)
tupel, sama denganx, y
dana, b
.list
tipe Python . Diedit karena memang ini membingungkan.Jika item tidak hashable, tetapi mendukung perbandingan pemesanan, Anda dapat mencoba:
sumber
complex
misalnya.Cara yang paling elegan, menurut saya, adalah
Ini adalah cara yang lebih baik daripada menggunakan set, yaitu
{a, b} == {y, x}
, seperti ditunjukkan dalam jawaban lain karena kita tidak perlu berpikir jika variabel-variabel tersebut dapat di hashable.sumber
Jika ini angka, Anda bisa menggunakannya
(x+y)==(a+b) and (x*y)==(a*b)
.Jika ini adalah barang yang sebanding, Anda bisa menggunakannya
min(x,y)==min(a,b) and max(x,y)==max(a,b)
.Tetapi
((x == a and y == b) or (x == b and y == a))
jelas, aman, dan lebih umum.sumber
Sebagai generalisasi untuk lebih dari dua variabel yang bisa kita gunakan
itertools.permutations
. Itu bukankita bisa menulis
Dan tentu saja dua versi variabel:
sumber
O(N*N!)
; Untuk 11 variabel, ini bisa memakan waktu lebih dari satu detik untuk selesai. (Saya memposting metode yang lebih cepat, tetapi masih membutuhkan waktuO(N^2)
, dan mulai mengambil alih satu detik pada variabel 10k; Jadi sepertinya ini dapat dilakukan dengan cepat atau secara umum (wrt. Hashability / keteraturan), tetapi tidak keduanya: P)Anda dapat menggunakan tupel untuk mewakili data Anda dan kemudian memeriksa set inklusi, seperti:
sumber
Anda sudah mendapatkan solusi yang paling mudah dibaca . Ada cara lain untuk mengekspresikan ini, mungkin dengan karakter yang lebih sedikit, tetapi mereka kurang mudah dibaca.
Bergantung pada nilai yang benar-benar mewakili taruhan terbaik Anda adalah untuk membungkus cek dalam fungsi dengan nama yang berbicara . Sebagai alternatif atau tambahan, Anda dapat memodelkan objek x, y dan a, b masing-masing dalam objek kelas tinggi khusus yang kemudian dapat Anda bandingkan dengan logika perbandingan dalam metode pemeriksaan kesetaraan kelas atau fungsi kustom khusus.
sumber
Tampaknya OP hanya peduli dengan kasus dua variabel, tetapi karena StackOverflow juga untuk mereka yang mencari pertanyaan yang sama nanti, saya akan mencoba untuk menangani kasus generik di sini secara rinci; Satu jawaban sebelumnya sudah menggunakan jawaban umum
itertools.permutations()
, tetapi metode itu mengarah keO(N*N!)
perbandingan, karena masing-masing adaN!
permutasi denganN
item. (Ini adalah motivasi utama untuk jawaban ini)Pertama, mari kita simpulkan bagaimana beberapa metode dalam jawaban sebelumnya berlaku untuk kasus umum, sebagai motivasi untuk metode yang disajikan di sini. Saya akan menggunakan
A
untuk merujuk(x, y)
danB
merujuk(a, b)
, yang bisa berupa tupel dengan panjang yang sewenang-wenang (tapi sama).set(A) == set(B)
cepat, tetapi hanya berfungsi jika nilainya hashable dan Anda dapat menjamin bahwa salah satu tupel tidak mengandung nilai duplikat apa pun. (Mis.{1, 1, 2} == {1, 2, 2}
, Seperti yang ditunjukkan oleh @ user2357112 di bawah jawaban @Daniel Mesejo)Metode sebelumnya dapat diperluas untuk bekerja dengan nilai duplikat dengan menggunakan kamus dengan jumlah, alih-alih set: (Ini masih memiliki batasan bahwa semua nilai harus dapat hashable, jadi mis. Nilai yang dapat diubah seperti
list
tidak akan berfungsi)sorted(A) == sorted(B)
tidak memerlukan nilai hashable, tetapi sedikit lebih lambat, dan sebaliknya membutuhkan nilai yang bisa dipesan. (Jadi mis. Tidakcomplex
akan bekerja)A in itertools.permutations(B)
tidak memerlukan nilai hashable atau orderable, tetapi seperti yang telah disebutkan, ia memilikiO(N*N!)
kompleksitas, sehingga bahkan dengan hanya 11 item, dapat membutuhkan waktu lebih dari satu detik untuk menyelesaikannya.Jadi, apakah ada cara untuk menjadi umum, tetapi apakah itu jauh lebih cepat? Mengapa ya, dengan "secara manual" memeriksa bahwa ada jumlah yang sama dari setiap item: (Kompleksitas yang satu ini
O(N^2)
, jadi ini juga tidak baik untuk input besar; Pada mesin saya, 10k item dapat membutuhkan waktu satu detik - tetapi dengan input yang lebih kecil, seperti 10 item, ini sama cepatnya dengan yang lain)Untuk mendapatkan kinerja terbaik, orang mungkin ingin mencoba
dict
metode berbasis pertama, kembali kesorted
metode berbasis jika itu gagal karena nilai-nilai yang tidak dapat dihancurkan, dan akhirnya jatuh kembali kecount
metode berbasis jika itu juga gagal karena nilai-nilai tidak teratur.sumber