Saya ingin membuat buffer melingkar yang efisien dengan python (dengan tujuan mengambil rata-rata nilai integer di buffer).
Apakah ini cara yang efisien untuk menggunakan daftar untuk mengumpulkan nilai?
def add_to_buffer( self, num ):
self.mylist.pop( 0 )
self.mylist.append( num )
Apa yang lebih efisien (dan mengapa)?
python
circular-buffer
jedierikb.dll
sumber
sumber
Jawaban:
Saya akan menggunakan
collections.deque
denganmaxlen
argAda resepnya di dokumen
deque
yang serupa dengan yang Anda inginkan. Penegasan saya bahwa ini yang paling efisien sepenuhnya didasarkan pada kenyataan bahwa itu diterapkan di C oleh kru yang sangat terampil yang memiliki kebiasaan untuk membuat kode kedudukan tertinggi.sumber
maxlen
ditentukan. O (n) dapat dimengerti ketikadeque
can tumbuh hingga tak terbatas, tetapi jikamaxlen
diberikan, pengindeksan sebuah elemen harus berupa waktu yang konstan.muncul dari kepala daftar menyebabkan seluruh daftar disalin, jadi tidak efisien
Anda sebaiknya menggunakan daftar / larik dengan ukuran tetap dan indeks yang bergerak melalui buffer saat Anda menambah / menghapus item
sumber
Berdasarkan jawaban MoonCactus , berikut adalah sebuah
circularlist
kelas. Perbedaannya dengan versinya adalah bahwa di sinic[0]
akan selalu memberikan elemen terlama, elemen tambahanc[-1]
terakhir,c[-2]
kedua dari belakang ... Ini lebih natural untuk aplikasi.Kelas:
[Diedit]: Menambahkan
data
parameter opsional untuk memungkinkan inisialisasi dari daftar yang ada, misalnya:sumber
c[-1]
selalu merupakan elemen yang tepat.__getitem__
melakukannya dengan benar.Deque Python lambat. Anda juga bisa menggunakan numpy.roll Bagaimana cara memutar angka dalam array numpy bentuk (n,) atau (n, 1)?
Dalam tolok ukur ini, deque adalah 448ms. Numpy.roll adalah 29ms http://scimusing.wordpress.com/2013/10/25/ring-buffers-in-pythonnumpy/
sumber
numpy.roll
mengembalikan salinan array, bukan?ok dengan penggunaan kelas deque, tetapi untuk permintaan pertanyaan (rata-rata) ini adalah solusi saya:
sumber
TypeError: 'numpy.float64' object is not callable
saat mencoba memanggilaverage
metodecollections
adalah bagian dari perpustakaan standar,numpy
bukan. Ketergantungan pada perpustakaan pihak ketiga akan membuat perpustakaan standar yang buruk.Meskipun sudah ada banyak jawaban bagus di sini, saya tidak dapat menemukan perbandingan langsung waktu untuk opsi yang disebutkan. Oleh karena itu, silakan temukan upaya saya yang sederhana dengan perbandingan di bawah ini.
Untuk tujuan pengujian saja, kelas dapat beralih antara
list
buffer berbasis-a, buffer berbasis-acollections.deque
, danNumpy.roll
buffer berbasis- a .Perhatikan bahwa file
update
metode hanya menambahkan satu nilai pada satu waktu, agar tetap sederhana.Di sistem saya, ini menghasilkan:
sumber
Bagaimana dengan solusi dari Python Cookbook , termasuk klasifikasi ulang dari instance buffer cincin ketika sudah penuh?
Kredit: Sébastien Keim
sumber
Anda juga bisa melihat resep Python yang cukup lama ini .
Ini adalah versi saya sendiri dengan NumPy array:
sumber
O(n)
waktu. Untuk mengimplementasikan buffer melingkar yang tepat , Anda harus memiliki indeks dan variabel ukuran, dan Anda perlu menangani kasus dengan benar saat data 'membungkus' di akhir buffer. Saat mengambil data, Anda mungkin harus menggabungkan dua bagian di awal dan akhir buffer.Yang ini tidak membutuhkan perpustakaan apa pun. Itu menumbuhkan daftar dan kemudian berputar di dalam menurut indeks.
Jejaknya sangat kecil (tidak ada perpustakaan), dan setidaknya berjalan dua kali lebih cepat dari dequeue. Ini memang bagus untuk menghitung rata-rata bergerak, tetapi perlu diketahui bahwa item tidak disimpan berdasarkan usia seperti di atas.
Untuk mendapatkan nilai rata-rata, misal:
Hasil dalam:
Ini sekitar 1/3 waktu ekuivalen dengan dequeue.
sumber
__getitem__
menjadi sedikit lebih kuat:self._data[(key + self._index + 1) % self._size]
?Saya pernah mengalami masalah ini sebelum melakukan pemrograman serial. Pada waktu lebih dari setahun yang lalu, saya juga tidak dapat menemukan implementasi yang efisien, jadi saya akhirnya menulis satu sebagai ekstensi C dan itu juga tersedia di pypi di bawah lisensi MIT. Ini sangat mendasar, hanya menangani buffer dari karakter bertanda 8-bit, tetapi memiliki panjang yang fleksibel, sehingga Anda dapat menggunakan Struct atau sesuatu di atasnya jika Anda membutuhkan sesuatu selain karakter. Saya melihat sekarang dengan pencarian google bahwa ada beberapa opsi hari ini, jadi Anda mungkin ingin melihatnya juga.
sumber
Jawaban Anda tidak benar. Circular buffer main memiliki dua prinsip (https://en.wikipedia.org/wiki/Circular_buffer )
kode Anda di bawah ini:
Mari pertimbangkan situasi di mana daftar itu penuh, dengan menggunakan kode Anda:
sekarang kami menambahkan 6, daftar diubah menjadi
item yang diharapkan 1 dalam daftar telah berubah posisinya
kode Anda adalah antrian, bukan buffer lingkaran.
Jawaban Basj menurut saya paling manjur.
Ngomong-ngomong, penyangga lingkaran dapat meningkatkan kinerja operasi untuk menambahkan item.
sumber
Dari Github:
https://github.com/heineman/python-data-structures/blob/master/2.%20Ubiquitous%20Lists/circBuffer.py
sumber
Pertanyaan aslinya adalah: buffer melingkar " efisien ". Menurut efisiensi yang diminta ini, jawaban dari aaronasterling tampaknya pasti benar. Menggunakan kelas khusus yang diprogram dengan Python dan membandingkan waktu pemrosesan dengan collections.deque menunjukkan akselerasi x5.2 kali dengan deque! Berikut kode yang sangat sederhana untuk mengujinya:
Untuk mengubah deque menjadi daftar, cukup gunakan:
Anda kemudian akan mendapatkan O (1) akses acak ke item deque. Tentu saja, ini hanya berguna jika Anda perlu melakukan banyak akses acak ke deque setelah menyetelnya sekali.
sumber
Ini menerapkan prinsip yang sama ke beberapa buffer yang dimaksudkan untuk menampung pesan teks terbaru.
sumber
Anda dapat memeriksa buffer melingkar ini berdasarkan larik numpy ukuran yang telah ditentukan sebelumnya. Idenya adalah Anda membuat buffer (mengalokasikan memori untuk array numpy) dan kemudian menambahkannya. Penyisipan data dan pengambilan sangat cepat. Saya telah membuat modul ini untuk tujuan yang sama seperti yang Anda butuhkan. Dalam kasus saya, saya memiliki perangkat yang menghasilkan data integer. Saya membaca data dan meletakkannya di buffer melingkar untuk analisis dan pemrosesan di masa mendatang.
sumber