Apakah ada cara pythonic untuk memeriksa apakah daftar sudah diurutkan dalam ASC
atauDESC
listtimestamps = [1, 2, 3, 5, 6, 7]
sesuatu seperti isttimestamps.isSorted()
itu kembali True
atau False
.
Saya ingin memasukkan daftar cap waktu untuk beberapa pesan dan memeriksa apakah transaksi muncul dalam urutan yang benar.
key
fungsi untuk digunakan.key=lambda x, y: x < y
membuat default yang bagus.def isSorted(x, key = lambda x: x): return all([key(x[i]) <= key(x[i + 1]) for i in xrange(len(x) - 1)])
operator.le
harus lebih cepat dari lambdal = [1, 2, 3, 4, 1, 6, 7, 8, 7] all(l[i] <= l[i+1] for i in xrange(len(l)-1))
cetak sebagai hasilnya:True
xrange
lagi, cukup gunakanrange
. Saya dapatkanNameError: name 'xrange' is not defined
ketika saya menjalankan kode itu. Saya beralih ke hanya menggunakanrange
bukanxrange
dan itu berfungsi dengan baik. Lihat: stackoverflow.com/questions/15014310/…Saya hanya akan menggunakan
kecuali itu daftar yang sangat besar dalam hal ini Anda mungkin ingin membuat fungsi kustom.
jika Anda hanya akan mengurutkannya jika tidak diurutkan, lupakan tanda centang dan urutkan.
dan jangan terlalu memikirkannya.
jika Anda menginginkan fungsi khusus, Anda dapat melakukan sesuatu seperti
Ini akan menjadi O (n) jika daftar sudah diurutkan (dan O (n) dalam satu
for
lingkaran pada saat itu!) Jadi, kecuali Anda mengharapkannya tidak diurutkan (dan cukup acak) sebagian besar waktu, saya akan, sekali lagi, cukup urutkan daftar.sumber
Bentuk iterator ini 10-15% lebih cepat daripada menggunakan pengindeksan bilangan bulat:
sumber
izip
danislice
dari itertools untuk membuatnya lebih cepat.Cara yang indah untuk mengimplementasikan ini adalah dengan menggunakan
imap
fungsi dariitertools
:Implementasi ini cepat dan bekerja pada semua iterables.
sumber
is_sorted(iter([1,2,3,2,5,8]))
atau generator yang setara. Anda perlu menggunakan iterator independen untuktail
, cobaitertools.tee
.iter(x) is x
untuk para iteratoritertools.imap
telah diubah namanya menjadi[__builtins__.]map
.Saya menjalankan tolok ukur
dan. Benchmark ini dijalankan pada MacBook Pro 2010 13 "(Core2 Duo 2.66GHz, 4GB 1067MHz DDR3 RAM, Mac OS X 10.6.5).sorted(lst, reverse=True) == lst
tercepat untuk daftar panjang, danall(l[i] >= l[i+1] for i in xrange(len(l)-1))
tercepat untuk daftar pendekUPDATE: Saya merevisi skrip sehingga Anda dapat menjalankannya langsung di sistem Anda sendiri. Versi sebelumnya memiliki bug. Juga, saya telah menambahkan input yang diurutkan dan yang tidak disortir.all(l[i] >= l[i+1] for i in xrange(len(l)-1))
sorted(l, reverse=True) == l
all(l[i] >= l[i+1] for i in xrange(len(l)-1))
all(l[i] >= l[i+1] for i in xrange(len(l)-1))
Jadi dalam banyak kasus ada pemenang yang jelas.UPDATE: jawaban aaronsterling (# 6 dan # 7) sebenarnya yang tercepat dalam semua kasus. # 7 adalah yang tercepat karena tidak memiliki lapisan tipuan untuk mencari kunci.
sumber
enumerate
salah.enumerate(l[1:])
harus diganti olehenumerate(l[1:], 1)
enumerate(l[1:])
denganenumerate(l[1:], 1)
Anda bisa menggantinyal[i-1]
denganl[i]
.L5=range(100); random.shuffle(L5)
maka # 5 relatif lambat. Dalam hal ini # 7 yang dimodifikasi lebih cepat secara keseluruhan codepad.org/xmWPxHQYSaya akan melakukan ini (mencuri dari banyak jawaban di sini [Aaron Sterling, Wai Yip Tung, agak dari Paul McGuire] dan sebagian besar Armin Ronacher ):
Satu hal yang menyenangkan: Anda tidak perlu menyadari iterable kedua untuk seri (tidak seperti dengan slice daftar).
sumber
key
.key
harus digunakan untuk mengubah item menjadi nilai yang sebanding.Saya menggunakan one-liner ini berdasarkan numpy.diff ():
Saya belum benar-benar menghitung waktunya terhadap metode lain, tapi saya menganggap itu lebih cepat daripada metode Python murni, terutama untuk n besar, karena loop di numpy.diff (mungkin) berjalan langsung di C (n-1 pengurangan diikuti oleh n -1 perbandingan).
Namun, Anda perlu berhati-hati jika x adalah int unsigned, yang dapat menyebabkan underflow integer diam di numpy.diff (), menghasilkan false positive. Ini versi modifikasi:
sumber
Ini mirip dengan jawaban teratas, tapi saya suka lebih baik karena menghindari pengindeksan eksplisit. Dengan asumsi daftar Anda memiliki nama
lst
, Anda dapat membuat(item, next_item)
tupel dari daftar Anda denganzip
:Di Python 3,
zip
sudah mengembalikan generator, di Python 2 Anda dapat menggunakanitertools.izip
untuk efisiensi memori yang lebih baik.Demo kecil:
Yang terakhir gagal ketika tuple
(3, 2)
dievaluasi.Bonus: memeriksa generator yang terbatas (!) Yang tidak dapat diindeks:
Pastikan untuk menggunakan di
itertools.izip
sini jika Anda menggunakan Python 2, jika tidak, Anda akan mengalahkan tujuan tidak harus membuat daftar dari generator.sumber
islice
untuk mengoptimalkan untuk mengiris. Juga di modul itertools.all(x <= y for x, y in izip(lst, islice(lst, 1)))
.SapphireSun benar. Anda bisa menggunakannya
lst.sort()
. Implementasi semacam Python (TimSort) memeriksa apakah daftar sudah diurutkan. Jika demikian sort () akan selesai dalam waktu linier. Kedengarannya seperti cara Pythonic untuk memastikan daftar diurutkan;)sumber
Meskipun saya tidak berpikir ada jaminan untuk itu
sorted
built-in memanggil fungsi CMP-nyai+1, i
, sepertinya memang demikian untuk CPython.Jadi Anda bisa melakukan sesuatu seperti:
Atau dengan cara ini (tanpa pernyataan if -> EAFP salah? ;-)):
sumber
Sama sekali tidak Pythonic, tetapi kita membutuhkan setidaknya satu
reduce()
jawaban, kan?Variabel akumulator hanya menyimpan nilai yang terakhir diperiksa, dan jika ada nilai yang lebih kecil dari nilai sebelumnya, akumulator diatur hingga tak terhingga (dan dengan demikian akan tetap tak terhingga pada akhirnya, karena 'nilai sebelumnya' akan selalu lebih besar daripada yang sekarang).
sumber
Seperti dicatat oleh @aaronsterling solusi berikut adalah yang terpendek dan tampaknya tercepat ketika array diurutkan dan tidak terlalu kecil: def is_sorted (lst): return (diurutkan (lst) == lst)
Jika sebagian besar waktu array tidak diurutkan, itu akan diinginkan untuk menggunakan solusi yang tidak memindai seluruh array dan mengembalikan False segera setelah awalan yang tidak disortir ditemukan. Berikut ini adalah solusi tercepat yang bisa saya temukan, tidak terlalu elegan:
Menggunakan tolok ukur Nathan Farrington, ini menghasilkan runtime yang lebih baik daripada menggunakan diurutkan (pertama) dalam semua kasus kecuali ketika berjalan pada daftar besar yang diurutkan.
Ini adalah hasil benchmark di komputer saya.
diurutkan (pertama) == solusi pertama
Solusi kedua:
sumber
Jika Anda menginginkan cara tercepat untuk numpy array, gunakan numba , yang jika Anda menggunakan conda harus sudah diinstal
Kode akan cepat karena akan dikompilasi oleh numba
lalu:
sumber
Hanya dengan menambahkan cara lain (walaupun itu membutuhkan modul tambahan)
iteration_utilities.all_monotone
::Untuk memeriksa pesanan DESC:
Ada juga
strict
parameter jika Anda perlu memeriksa secara ketat (jika elemen berturut-turut tidak boleh sama) urutan monoton.Ini bukan masalah dalam kasus Anda tetapi jika urutan Anda berisi
nan
nilai maka beberapa metode akan gagal, misalnya dengan diurutkan:Perhatikan bahwa
iteration_utilities.all_monotone
kinerjanya lebih cepat dibandingkan dengan solusi lain yang disebutkan di sini terutama untuk input yang tidak disortir (lihat benchmark ).sumber
Malas
sumber
all(a <= b for a, b in zip(l, l[1:]))
l
generator dan tidak mendukung slicing.Python 3.6.8
sumber
Cara termudah:
sumber
Nilai reduksi yang diturunkan adalah 3 bagian tupel ( diurutkanSoFarFlag , firstTimeFlag , lastElementValue ). Ini awalnya dimulai dengan (
True
,True
,None
), yang juga digunakan sebagai hasil untuk daftar kosong (dianggap sebagai diurutkan karena tidak ada out-of-order elemen). Saat memproses setiap elemen, ia menghitung nilai baru untuk tuple (menggunakan nilai tuple sebelumnya dengan elementValue berikutnya):Hasil akhir dari reduksi adalah tuple dari:
Nilai pertama adalah yang kami minati, jadi kami gunakan
[0]
untuk mengambilnya dari hasil pengurangan.sumber
Karena saya tidak melihat opsi ini di atas, saya akan menambahkannya ke semua jawaban. Biarkan tandai daftar dengan
l
, lalu:sumber
Solusi menggunakan ekspresi penugasan (ditambahkan dengan Python 3.8):
Memberi:
sumber
Ini sebenarnya cara terpendek untuk melakukannya menggunakan rekursi:
jika itu Diurutkan akan mencetak Benar yang lain akan mencetak Salah
sumber
RuntimeError: maximum recursion depth exceeded
daftar panjang. Cobaany_list = range(1000)
.Bagaimana dengan yang ini ? Sederhana dan mudah.
sumber
Jelas berfungsi di Python 3 dan di atasnya untuk bilangan bulat atau string:
================================================== ===================
Cara lain untuk menemukan apakah daftar yang diberikan diurutkan atau tidak
sumber