দক্ষ বিজ্ঞপ্তি বাফার?


109

আমি পাইথনটিতে একটি কার্যকর বিজ্ঞপ্তি বাফার তৈরি করতে চাই ( বাফারে পূর্ণসংখ্যার গড় গড় নেওয়ার লক্ষ্য নিয়ে)।

মান সংগ্রহের জন্য কোনও তালিকা ব্যবহারের জন্য এটি কি কার্যকর উপায়?

def add_to_buffer( self, num ):
    self.mylist.pop( 0 )
    self.mylist.append( num )

আরও দক্ষ (এবং কেন) হবে?


এটি বিজ্ঞপ্তিযুক্ত বাফার বাস্তবায়নের কার্যকর উপায় নয় কারণ তালিকায় পপ (0) ও (এন) অপারেশন। পপ (0) তালিকার প্রথম উপাদানটি সরিয়ে দেয় এবং সমস্ত উপাদানকে বামে স্থানান্তর করতে হবে। পরিবর্তে ম্যাক্সেলেন বৈশিষ্ট্য সহ কালেকশন.ডেক ব্যবহার করুন। ডেকের অ্যাপেনড এবং পপ করার জন্য ও (1) অপারেশন রয়েছে।
ভ্লাদ বেজডেন

উত্তর:


204

আমি collections.dequeএকটি maxlenআরগ দিয়ে ব্যবহার করব

>>> import collections
>>> d = collections.deque(maxlen=10)
>>> d
deque([], maxlen=10)
>>> for i in xrange(20):
...     d.append(i)
... 
>>> d
deque([10, 11, 12, 13, 14, 15, 16, 17, 18, 19], maxlen=10)

ডক্সের জন্য একটি রেসিপি রয়েছে dequeযা আপনি যা চান তার সাথে মিলে যায়। আমার দাবি যে এটি সবচেয়ে দক্ষ এটি সম্পূর্ণরূপে নির্ভর করে যে এটি সিতে বাস্তবায়িত হয়েছিল এমন একটি অবিশ্বাস্যভাবে দক্ষ ক্রু দ্বারা যা শীর্ষস্থানীয় কোডটি ক্র্যাঙ্ক করার অভ্যাসে রয়েছে।


7
+1 হ্যাঁ এটি দুর্দান্ত ব্যাটারি অন্তর্ভুক্ত উপায়। বিজ্ঞপ্তি বাফারটির জন্য অপারেশনগুলি হ'ল (1) এবং আপনি যেমন বলেছিলেন অতিরিক্ত ওভারহেড সি-তে রয়েছে, তবুও বেশ দ্রুত হওয়া উচিত
জন লা রু

7
আমি এই সমাধানটি পছন্দ করি না কারণ maxlenসংজ্ঞায়িত হয়ে গেলে ডক্সগুলি ও (1) এলোমেলো অ্যাক্সেসের গ্যারান্টি দেয় না । ও (এন) বোধগম্য হয় যখন dequeঅনন্তটি বৃদ্ধি পেতে পারে, তবে যদি maxlenদেওয়া হয় তবে কোনও উপাদানকে সূচীকরণ করা স্থির সময় হওয়া উচিত।
lvella

1
আমার অনুমান যে এটি কোনও লিঙ্কযুক্ত তালিকা হিসাবে প্রয়োগ করা হয়েছে এবং অ্যারে নয়।
ই-সন্তুষ্ট

1
ডান সম্পর্কে মনে হচ্ছে, যদি নীচে আমার উত্তরের সময়গুলি সঠিক হয়।
djvg

13

একটি তালিকার মাথা থেকে পপিংয়ের ফলে পুরো তালিকাটি অনুলিপি করা হয়, তাই এটি অক্ষম

পরিবর্তে আপনার নির্দিষ্ট আকারের একটি তালিকা / অ্যারে এবং একটি সূচি ব্যবহার করা উচিত যা আপনি বাফারগুলিতে আইটেমগুলি যুক্ত / অপসারণ করার সাথে সাথে চলে


4
একমত। এটি যতই মার্জিত বা অকার্যকর দেখায় বা ভাষা ব্যবহার করা যাই হোক না কেন। বাস্তবে, আপনি আবর্জনা সংগ্রহকারীকে যত কম বিরক্ত করবেন (বা হিপ ম্যানেজার বা পেজিং / ম্যাপিং প্রক্রিয়া বা যা কিছু প্রকৃত স্মৃতি যাদু করে) তত ভাল।

@ রকেটসার্জন এটি কোনও যাদু নয়, এটি এমন একটি অ্যারে যার প্রথম উপাদানটি মুছে ফেলা হয়েছে। সুতরাং আকারের অ্যারের জন্য এন এর অর্থ এন -১ অনুলিপি অপারেশন। এখানে কোনও জঞ্জাল সংগ্রহকারী বা অনুরূপ ডিভাইস জড়িত নেই।
খ্রিস্টান

3
আমি রাজী. কিছু লোক মনে করে এর চেয়ে এটি করা আরও সহজ। কেবলমাত্র ক্রমবর্ধমান কাউন্টার ব্যবহার করুন এবং আইটেমটি অ্যাক্সেস করার সময় মডুলো অপারেটর (% অ্যারেলেন) ব্যবহার করুন।
আন্দ্রে ব্লাম

আদর্শ, আপনি আমার পোস্টটি উপরে পরীক্ষা করতে পারেন, আমি এটি
এটিই

10

মুনক্যাকটাসের উত্তরের ভিত্তিতে , এখানে একটি circularlistশ্রেণি রয়েছে is তার সংস্করণটির সাথে পার্থক্যটি হ'ল এখানে c[0]সর্বদা প্রাচীনতম-সংযোজনিত উপাদান, c[-1]সর্বশেষতম সংযোজনিত উপাদান, c[-2]পেনাল্টিমেট ... অ্যাপ্লিকেশনগুলির জন্য এটি আরও স্বাভাবিক।

c = circularlist(4)
c.append(1); print c, c[0], c[-1]    #[1]              1, 1
c.append(2); print c, c[0], c[-1]    #[1, 2]           1, 2
c.append(3); print c, c[0], c[-1]    #[1, 2, 3]        1, 3
c.append(8); print c, c[0], c[-1]    #[1, 2, 3, 8]     1, 8
c.append(10); print c, c[0], c[-1]   #[10, 2, 3, 8]    2, 10
c.append(11); print c, c[0], c[-1]   #[10, 11, 3, 8]   3, 11

ক্লাস:

class circularlist(object):
    def __init__(self, size, data = []):
        """Initialization"""
        self.index = 0
        self.size = size
        self._data = list(data)[-size:]

    def append(self, value):
        """Append an element"""
        if len(self._data) == self.size:
            self._data[self.index] = value
        else:
            self._data.append(value)
        self.index = (self.index + 1) % self.size

    def __getitem__(self, key):
        """Get element by index, relative to the current index"""
        if len(self._data) == self.size:
            return(self._data[(key + self.index) % self.size])
        else:
            return(self._data[key])

    def __repr__(self):
        """Return string representation"""
        return self._data.__repr__() + ' (' + str(len(self._data))+' items)'

[সম্পাদিত]:data বিদ্যমান তালিকা থেকে সূচনা করার জন্য al চ্ছিক প্যারামিটার যুক্ত করা হয়েছে, যেমন:

circularlist(4, [1, 2, 3, 4, 5])      #  [2, 3, 4, 5] (4 items)
circularlist(4, set([1, 2, 3, 4, 5])) #  [2, 3, 4, 5] (4 items)
circularlist(4, (1, 2, 3, 4, 5))      #  [2, 3, 4, 5] (4 items)

ভাল সংযোজন। পাইথন তালিকা ইতিমধ্যে নেতিবাচক সূচকের দিই, কিন্তু (-1), যেমন প্রত্যাশিত মান ফিরে আসতে পারবেন না একবার বিজ্ঞপ্তি বাফার, পূর্ণ, যেহেতু লিস্টে "সর্বশেষ" উপরন্তু শেষ পর্যন্ত মধ্যে তালিকা।
মুনক্যাকটাস 25:58

1
এটি @ মুনক্যাকটাসের কাজ করে, উত্তরের উপরে আমি যে examples টি উদাহরণ দিয়েছি তা দেখুন; সর্বশেষে, আপনি দেখতে পারেন c[-1]সর্বদা সঠিক উপাদান। __getitem__এটা ঠিক আছে।
বাসজ

ওহ হ্যাঁ, মানে আমার ব্যর্থ হয়েছে, আপনার নয়, দুঃখিত: ডিআই আমার মন্তব্যকে আরও পরিষ্কার করবে! - ওহ আমি পারছি না, মন্তব্যটি খুব পুরানো।
মুনক্যাকটাস

চমৎকার সহজ সমাধান। বিদ্যমান তথ্য থেকে তালিকার সূচনা করার জন্য আমি একটি alচ্ছিক যুক্তি যুক্ত করেছি, এটি সেভাবেই আরও অজগর যন্ত্রের।
অ্যারওলোফাইল

9

পাইথনের ডেকা ধীর। আপনি এর পরিবর্তে numpy.rol ব্যবহার করতে পারেন আপনি কীভাবে আকার (এন,) বা (এন, 1) এর একটি বিন্যাস অ্যারে সংখ্যাগুলি ঘোরান?

এই মানদণ্ডে, ডেকু 448 মিমি। নম্পি.রোলটি 29 মিমি http://scimused.wordpress.com/2013/10/25/ring-buffers-in-pythonnumpy/


1
কিন্তু numpy.rollঅ্যারের একটি অনুলিপি ফিরে আসে, তাই না?
djvg

3
এই উত্তরটি খুব বিভ্রান্তিমূলক - পাইথনের ডেকটি বেশ দ্রুত বলে মনে হচ্ছে, তবে আপনি যে ন্যাশনালমার্কে লিঙ্ক করেছেন তার মধ্যে ন্যাপি অ্যারে থেকে রূপান্তর করা এটিকে যথেষ্ট ধীর করে দেয়।
xitrium

7

ডেক ক্লাস ব্যবহারের সাথে ঠিক আছে, তবে প্রশ্নের প্রয়োজনীয়তার জন্য (গড়) এটি আমার সমাধান:

>>> from collections import deque
>>> class CircularBuffer(deque):
...     def __init__(self, size=0):
...             super(CircularBuffer, self).__init__(maxlen=size)
...     @property
...     def average(self):  # TODO: Make type check for integer or floats
...             return sum(self)/len(self)
...
>>>
>>> cb = CircularBuffer(size=10)
>>> for i in range(20):
...     cb.append(i)
...     print "@%s, Average: %s" % (cb, cb.average)
...
@deque([0], maxlen=10), Average: 0
@deque([0, 1], maxlen=10), Average: 0
@deque([0, 1, 2], maxlen=10), Average: 1
@deque([0, 1, 2, 3], maxlen=10), Average: 1
@deque([0, 1, 2, 3, 4], maxlen=10), Average: 2
@deque([0, 1, 2, 3, 4, 5], maxlen=10), Average: 2
@deque([0, 1, 2, 3, 4, 5, 6], maxlen=10), Average: 3
@deque([0, 1, 2, 3, 4, 5, 6, 7], maxlen=10), Average: 3
@deque([0, 1, 2, 3, 4, 5, 6, 7, 8], maxlen=10), Average: 4
@deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10), Average: 4
@deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], maxlen=10), Average: 5
@deque([2, 3, 4, 5, 6, 7, 8, 9, 10, 11], maxlen=10), Average: 6
@deque([3, 4, 5, 6, 7, 8, 9, 10, 11, 12], maxlen=10), Average: 7
@deque([4, 5, 6, 7, 8, 9, 10, 11, 12, 13], maxlen=10), Average: 8
@deque([5, 6, 7, 8, 9, 10, 11, 12, 13, 14], maxlen=10), Average: 9
@deque([6, 7, 8, 9, 10, 11, 12, 13, 14, 15], maxlen=10), Average: 10
@deque([7, 8, 9, 10, 11, 12, 13, 14, 15, 16], maxlen=10), Average: 11
@deque([8, 9, 10, 11, 12, 13, 14, 15, 16, 17], maxlen=10), Average: 12
@deque([9, 10, 11, 12, 13, 14, 15, 16, 17, 18], maxlen=10), Average: 13
@deque([10, 11, 12, 13, 14, 15, 16, 17, 18, 19], maxlen=10), Average: 14

পদ্ধতিটি TypeError: 'numpy.float64' object is not callableকল করার চেষ্টা করার সময় আমি পেয়েছিaverage
স্কেলগুলি

হ্যাঁ ... প্রকৃতপক্ষে আমি অনুমান করি যে ডেক আভ্যন্তরীণ বিন্যাস অভ্যন্তরীণভাবে ব্যবহার করে (@ প্রোপার্টি অপসারণের পরে এটি ভাল কাজ করে)
স্কেলগুলি

17
আমি গ্যারান্টি দিচ্ছি যে ডেক অভ্যন্তরীণভাবে নমপি অ্যারে ব্যবহার করে না। collectionsস্ট্যান্ডার্ড লাইব্রেরির অংশ, numpyনা। তৃতীয় পক্ষের লাইব্রেরিতে নির্ভরতাগুলি একটি ভয়ানক স্ট্যান্ডার্ড গ্রন্থাগার তৈরি করবে।

6

যদিও এখানে ইতিমধ্যে দুর্দান্ত সংখ্যার উত্তর রয়েছে তবে আমি উল্লিখিত বিকল্পগুলির জন্য সময়গুলির সরাসরি কোনও তুলনা খুঁজে পাইনি। অতএব, দয়া করে নীচের তুলনায় আমার নম্র প্রচেষ্টাটি সন্ধান করুন।

কেবল পরীক্ষার উদ্দেশ্যে, ক্লাসটি একটি listবেসড বাফার, একটি collections.dequeভিত্তিক বাফার এবং একটি এর মধ্যে স্যুইচ করতে পারেNumpy.roll ভিত্তিক বাফারের ।

নোট করুন যে updateপদ্ধতিটি একসাথে কেবল একটি মান যুক্ত করে, এটিকে সহজ রাখতে।

import numpy
import timeit
import collections


class CircularBuffer(object):
    buffer_methods = ('list', 'deque', 'roll')

    def __init__(self, buffer_size, buffer_method):
        self.content = None
        self.size = buffer_size
        self.method = buffer_method

    def update(self, scalar):
        if self.method == self.buffer_methods[0]:
            # Use list
            try:
                self.content.append(scalar)
                self.content.pop(0)
            except AttributeError:
                self.content = [0.] * self.size
        elif self.method == self.buffer_methods[1]:
            # Use collections.deque
            try:
                self.content.append(scalar)
            except AttributeError:
                self.content = collections.deque([0.] * self.size,
                                                 maxlen=self.size)
        elif self.method == self.buffer_methods[2]:
            # Use Numpy.roll
            try:
                self.content = numpy.roll(self.content, -1)
                self.content[-1] = scalar
            except IndexError:
                self.content = numpy.zeros(self.size, dtype=float)

# Testing and Timing
circular_buffer_size = 100
circular_buffers = [CircularBuffer(buffer_size=circular_buffer_size,
                                   buffer_method=method)
                    for method in CircularBuffer.buffer_methods]
timeit_iterations = 1e4
timeit_setup = 'from __main__ import circular_buffers'
timeit_results = []
for i, cb in enumerate(circular_buffers):
    # We add a convenient number of convenient values (see equality test below)
    code = '[circular_buffers[{}].update(float(j)) for j in range({})]'.format(
        i, circular_buffer_size)
    # Testing
    eval(code)
    buffer_content = [item for item in cb.content]
    assert buffer_content == range(circular_buffer_size)
    # Timing
    timeit_results.append(
        timeit.timeit(code, setup=timeit_setup, number=int(timeit_iterations)))
    print '{}: total {:.2f}s ({:.2f}ms per iteration)'.format(
        cb.method, timeit_results[-1],
        timeit_results[-1] / timeit_iterations * 1e3)

আমার সিস্টেমে এটি ফলন করে:

list:  total 1.06s (0.11ms per iteration)
deque: total 0.87s (0.09ms per iteration)
roll:  total 6.27s (0.63ms per iteration)

4

পাইথন কুকবুক থেকে সমাধানটি কীভাবে পূর্ণ হবে যখন রিং বাফার উদাহরণটির পুনঃব্যবস্থাপনা সহ?

class RingBuffer:
    """ class that implements a not-yet-full buffer """
    def __init__(self,size_max):
        self.max = size_max
        self.data = []

    class __Full:
        """ class that implements a full buffer """
        def append(self, x):
            """ Append an element overwriting the oldest one. """
            self.data[self.cur] = x
            self.cur = (self.cur+1) % self.max
        def get(self):
            """ return list of elements in correct order """
            return self.data[self.cur:]+self.data[:self.cur]

    def append(self,x):
        """append an element at the end of the buffer"""
        self.data.append(x)
        if len(self.data) == self.max:
            self.cur = 0
            # Permanently change self's class from non-full to full
            self.__class__ = self.__Full

    def get(self):
        """ Return a list of elements from the oldest to the newest. """
        return self.data

# sample usage
if __name__=='__main__':
    x=RingBuffer(5)
    x.append(1); x.append(2); x.append(3); x.append(4)
    print(x.__class__, x.get())
    x.append(5)
    print(x.__class__, x.get())
    x.append(6)
    print(x.data, x.get())
    x.append(7); x.append(8); x.append(9); x.append(10)
    print(x.data, x.get())

বাস্তবায়নের ক্ষেত্রে উল্লেখযোগ্য নকশার পছন্দটি হ'ল, যেহেতু এই বিষয়গুলি তাদের জীবনকালের কোনও সময়ে একটি অবিশ্বাস্য রাষ্ট্রের রূপান্তর হয় go অ-পূর্ণ-বাফার থেকে ফুল-বাফার (এবং সেই সময়ে আচরণের পরিবর্তন) - আমি এটি পরিবর্তনের মাধ্যমে মডেল করেছি self.__class__। এটি পাইথন ২.২-তেও কাজ করে, যতক্ষণ না উভয় শ্রেণীর একই স্লট থাকে (উদাহরণস্বরূপ, এটি দুটি ক্লাসিক ক্লাসের জন্য কাজ করে, যেমন রিংবফার এবং__Full এই রেসিপিটিতে)।

উদাহরণের শ্রেণিটি পরিবর্তন করা অনেক ভাষায় অদ্ভুত হতে পারে তবে এটি এই রেসিপিতে যেমন আচরণকে ব্যাপকভাবে প্রভাবিত করে এমন সাময়িক, বৃহত্তর, অপরিবর্তনীয় এবং রাষ্ট্রের বিচ্ছিন্ন পরিবর্তনের প্রতিনিধিত্ব করার অন্যান্য উপায়গুলির একটি পাইথনিক বিকল্প is পাইথন এটি সমস্ত ধরণের ক্লাসের জন্য সমর্থন করে Good

ক্রেডিট: সাবস্টিয়ান কেইম


আমি এই বনাম ডেকের কিছু গতি পরীক্ষা করেছি। এটি ডেকির চেয়ে প্রায় 7 গুণ ধীর।
পলিমেশ

@ পলিমেশ দুর্দান্ত, আপনি লেখককে জানাবেন!
d8aninja

1
যে বিন্দু কি হবে? এটি একটি পুরানো প্রকাশিত নথি। আমার মন্তব্যের মূল বক্তব্যটি হ'ল অন্যদের জানান যে এই উত্তরটি পুরানো এবং তার পরিবর্তে উপযুক্ত ব্যবহার করা উচিত।
পলিমেশ

@ পলিমেশ যখন প্রকাশ করেছেন তখন এটি সম্ভবত আরও ধীর ছিল; লেখকের সাথে যোগাযোগের জন্য নির্দেশাবলী বইয়ের ভূমিকাতে রয়েছে। আমি কেবল একটি সম্ভাব্য বিকল্প সম্পর্কিত করছি। এছাড়াও, "যদি কেবল গতিই সেরা মেট্রিক হত; হায় তবে এটি কেবল ভালই হতে পারে।"
d8aninja

3

আপনি বেশ পুরানো পাইথন রেসিপিটিও দেখতে পারেন ।

নম্পপি অ্যারে সহ আমার নিজস্ব সংস্করণটি এখানে:

#!/usr/bin/env python

import numpy as np

class RingBuffer(object):
    def __init__(self, size_max, default_value=0.0, dtype=float):
        """initialization"""
        self.size_max = size_max

        self._data = np.empty(size_max, dtype=dtype)
        self._data.fill(default_value)

        self.size = 0

    def append(self, value):
        """append an element"""
        self._data = np.roll(self._data, 1)
        self._data[0] = value 

        self.size += 1

        if self.size == self.size_max:
            self.__class__  = RingBufferFull

    def get_all(self):
        """return a list of elements from the oldest to the newest"""
        return(self._data)

    def get_partial(self):
        return(self.get_all()[0:self.size])

    def __getitem__(self, key):
        """get element"""
        return(self._data[key])

    def __repr__(self):
        """return string representation"""
        s = self._data.__repr__()
        s = s + '\t' + str(self.size)
        s = s + '\t' + self.get_all()[::-1].__repr__()
        s = s + '\t' + self.get_partial()[::-1].__repr__()
        return(s)

class RingBufferFull(RingBuffer):
    def append(self, value):
        """append an element when buffer is full"""
        self._data = np.roll(self._data, 1)
        self._data[0] = value

4
নাম্পি ব্যবহারের জন্য +1, তবে একটি বিজ্ঞপ্তি বাফার প্রয়োগ না করার জন্য -1 আপনি যেভাবে এটি প্রয়োগ করেছেন, প্রতিবার আপনি যখন কোনও একক উপাদান যুক্ত করেন তখন সমস্ত ডেটা স্থানান্তরিত হয়, এর জন্য O(n)সময় ব্যয় হয় । সঠিক বৃত্তাকার বাফার বাস্তবায়নের জন্য আপনার সূচি এবং আকারের ভেরিয়েবল উভয়ই থাকা উচিত এবং যখন বাফারের শেষে ডেটা 'চারপাশে মোড়ানো হয়' তখন আপনার কেসটি সঠিকভাবে পরিচালনা করতে হবে। ডেটা পুনরুদ্ধার করার সময়, আপনাকে বাফারের শুরু এবং শেষে দুটি বিভাগকে একত্রে করতে হতে পারে।
বাস সুইঙ্কসেলস

2

এটির জন্য কোনও লাইব্রেরির প্রয়োজন নেই। এটি একটি তালিকা বৃদ্ধি করে এবং তারপরে সূচকের আওতায় চলে cycle

পায়ের ছাপ খুব ছোট (কোনও লাইব্রেরি নেই), এবং এটি কমপক্ষে ডেকুয়ের চেয়ে দ্বিগুণ দ্রুত চলে। এটি প্রকৃতপক্ষে চলমান গড় গণনা করা ভাল, তবে সচেতন থাকুন যে আইটেমগুলি উপরে বয়স অনুসারে বাছাই করা হয়নি।

class CircularBuffer(object):
    def __init__(self, size):
        """initialization"""
        self.index= 0
        self.size= size
        self._data = []

    def record(self, value):
        """append an element"""
        if len(self._data) == self.size:
            self._data[self.index]= value
        else:
            self._data.append(value)
        self.index= (self.index + 1) % self.size

    def __getitem__(self, key):
        """get element by index like a regular array"""
        return(self._data[key])

    def __repr__(self):
        """return string representation"""
        return self._data.__repr__() + ' (' + str(len(self._data))+' items)'

    def get_all(self):
        """return a list of all the elements"""
        return(self._data)

গড় মান পেতে, যেমন:

q= CircularBuffer(1000000);
for i in range(40000):
    q.record(i);
print "capacity=", q.size
print "stored=", len(q.get_all())
print "average=", sum(q.get_all()) / len(q.get_all())

ফলাফল স্বরূপ:

capacity= 1000000
stored= 40000
average= 19999

real 0m0.024s
user 0m0.020s
sys  0m0.000s

এটি প্রায় 1/3 সময় ডেকিউ সঙ্গে সমতুল্য সময়।


1
আপনার না করা উচিত __getitem__একটি বিট আরো শক্তিশালী হতে: self._data[(key + self._index + 1) % self._size]?
মতিন উলহাক

আপনি কেন +1 এ স্থানান্তর করতে চান? এখন, হ্যাঁ, ধারণার জন্য নীচে বাসজ বৈকল্পিকটি দেখুন
মুনক্যাকটাস

1

সিরিয়াল প্রোগ্রামিং করার আগে আমার এই সমস্যা হয়েছিল। ঠিক এক বছর আগে, আমি কোনও কার্যকর বাস্তবায়ন খুঁজে পাইনি, তাই আমি সি এক্সটেনশন হিসাবে একটি লেখা লিখে শেষ করেছিলাম এবং এটি এমআইটি লাইসেন্সের অধীনে পাইপিতেও পাওয়া যায় । এটি দুর্দান্ত বেসিক, কেবলমাত্র 8-বিট স্বাক্ষরিত অক্ষরের বাফারগুলি পরিচালনা করে, তবে এটি নমনীয় দৈর্ঘ্যের হয়, তাই আপনি চরগুলি ব্যতীত অন্য কিছু প্রয়োজন হলে আপনি স্ট্রাক্ট বা এর উপরে কিছু ব্যবহার করতে পারেন। আমি এখন একটি গুগল অনুসন্ধানের সাথে দেখতে পাচ্ছি যে আজকাল বেশ কয়েকটি বিকল্প রয়েছে, তাই আপনিও সেগুলি দেখতে চাইবেন।


1

আপনি উত্তর সঠিক না। বিজ্ঞপ্তি বাফার প্রধানের দুটি প্রিপিসিল রয়েছে (https://en.wikedia.org/wiki/Circular_buffer )

  1. বাফারের লেন্ট সেট করা আছে;
  2. যে প্রথম আসবে, সে প্রথম যাবে;
  3. আপনি যখন কোনও আইটেম যুক্ত বা মুছবেন তখন অন্যান্য আইটেমগুলির অবস্থানটি সরানো উচিত নয়

আপনার কোড নীচে:

def add_to_buffer( self, num ):
    self.mylist.pop( 0 )
    self.mylist.append( num )

আপনার কোড ব্যবহার করে তালিকাটি পূর্ণ রয়েছে এমন একটি পরিস্থিতি বিবেচনা করুন:

self.mylist = [1, 2, 3, 4, 5]

এখন আমরা 6 সংযোজন, তালিকা পরিবর্তন করা হয়

self.mylist = [2, 3, 4, 5, 6]

তালিকায় থাকা 1 টি আইটেমগুলি তাদের অবস্থান পরিবর্তন করেছে expect

আপনার কোডটি একটি সার্কেল, কোনও বৃত্ত বাফার নয়।

বাসজের উত্তর, আমি মনে করি সবচেয়ে কার্যকর one

উপায় দ্বারা, একটি চেনাশোনা বাফার একটি আইটেম যুক্ত করতে ক্রিয়াকলাপটির পারফরম্যান্সকে আরও বাড়িয়ে তুলতে পারে।


1

গিথুব থেকে:

class CircularBuffer:

    def __init__(self, size):
        """Store buffer in given storage."""
        self.buffer = [None]*size
        self.low = 0
        self.high = 0
        self.size = size
        self.count = 0

    def isEmpty(self):
        """Determines if buffer is empty."""
        return self.count == 0

    def isFull(self):
        """Determines if buffer is full."""
        return self.count == self.size

    def __len__(self):
        """Returns number of elements in buffer."""
        return self.count

    def add(self, value):
        """Adds value to buffer, overwrite as needed."""
        if self.isFull():
            self.low = (self.low+1) % self.size
        else:
            self.count += 1
        self.buffer[self.high] = value
        self.high = (self.high + 1) % self.size

    def remove(self):
        """Removes oldest value from non-empty buffer."""
        if self.count == 0:
            raise Exception ("Circular Buffer is empty");
        value = self.buffer[self.low]
        self.low = (self.low + 1) % self.size
        self.count -= 1
        return value

    def __iter__(self):
        """Return elements in the circular buffer in order using iterator."""
        idx = self.low
        num = self.count
        while num > 0:
            yield self.buffer[idx]
            idx = (idx + 1) % self.size
            num -= 1

    def __repr__(self):
        """String representation of circular buffer."""
        if self.isEmpty():
            return 'cb:[]'

        return 'cb:[' + ','.join(map(str,self)) + ']'

https://github.com/heineman/python-data-structures/blob/master/2.%20Ubiquitous%20Lists/circBuffer.py


0

মূল প্রশ্নটি ছিল: " দক্ষ " বিজ্ঞপ্তি বাফার। এই দক্ষতার জন্য জিজ্ঞাসা করা অনুসারে, অ্যারোনাস্টারিংয়ের উত্তর যথাযথভাবে সঠিক বলে মনে হচ্ছে। পাইথনে প্রোগ্রামেড ডেডিকেটেড ক্লাস ব্যবহার করা এবং কালেকশন.ডেকের সাথে টাইম প্রসেসিংয়ের তুলনা করা ডেকের সাথে একটি x5.2 বারের ত্বরণ দেখায়! এটি পরীক্ষা করার জন্য এখানে খুব সাধারণ কোডটি রয়েছে:

class cb:
    def __init__(self, size):
        self.b = [0]*size
        self.i = 0
        self.sz = size
    def append(self, v):
        self.b[self.i] = v
        self.i = (self.i + 1) % self.sz

b = cb(1000)
for i in range(10000):
    b.append(i)
# called 200 times, this lasts 1.097 second on my laptop

from collections import deque
b = deque( [], 1000 )
for i in range(10000):
    b.append(i)
# called 200 times, this lasts 0.211 second on my laptop

কোনও ডীককে তালিকায় রূপান্তর করতে, কেবলমাত্র এটি ব্যবহার করুন:

my_list = [v for v in my_deque]

এরপরে আপনি ও (1) ডেক আইটেমগুলিতে এলোমেলো অ্যাক্সেস পাবেন। অবশ্যই, এটি কেবল তখনই মূল্যবান যখন আপনার একবার স্থাপন করার পরে ডেকের কাছে অনেকগুলি এলোমেলো অ্যাক্সেস করতে হবে।


0

এটি সাম্প্রতিকতম পাঠ্য বার্তাগুলি ধারণ করার উদ্দেশ্যে কিছু বাফারে একই অধ্যক্ষ প্রয়োগ করছে।

import time
import datetime
import sys, getopt

class textbffr(object):
    def __init__(self, size_max):
        #initialization
        self.posn_max = size_max-1
        self._data = [""]*(size_max)
        self.posn = self.posn_max

    def append(self, value):
        #append an element
        if self.posn == self.posn_max:
            self.posn = 0
            self._data[self.posn] = value   
        else:
            self.posn += 1
            self._data[self.posn] = value

    def __getitem__(self, key):
        #return stored element
        if (key + self.posn+1) > self.posn_max:
            return(self._data[key - (self.posn_max-self.posn)])
        else:
            return(self._data[key + self.posn+1])


def print_bffr(bffr,bffer_max): 
    for ind in range(0,bffer_max):
        stored = bffr[ind]
        if stored != "":
            print(stored)
    print ( '\n' )

def make_time_text(time_value):
    return(str(time_value.month).zfill(2) + str(time_value.day).zfill(2)
      + str(time_value.hour).zfill(2) +  str(time_value.minute).zfill(2)
      + str(time_value.second).zfill(2))


def main(argv):
    #Set things up 
    starttime = datetime.datetime.now()
    log_max = 5
    status_max = 7
    log_bffr = textbffr(log_max)
    status_bffr = textbffr(status_max)
    scan_count = 1

    #Main Loop
    # every 10 secounds write a line with the time and the scan count.
    while True: 

        time_text = make_time_text(datetime.datetime.now())
        #create next messages and store in buffers
        status_bffr.append(str(scan_count).zfill(6) + " :  Status is just fine at : " + time_text)
        log_bffr.append(str(scan_count).zfill(6) + " : " + time_text + " : Logging Text ")

        #print whole buffers so far
        print_bffr(log_bffr,log_max)
        print_bffr(status_bffr,status_max)

        time.sleep(2)
        scan_count += 1 

if __name__ == '__main__':
    main(sys.argv[1:])  

0

আপনি পূর্বনির্ধারিত আকারের নম্পি অ্যারের ভিত্তিতে এই বিজ্ঞপ্তি বাফারটি পরীক্ষা করে দেখতে পারেন । ধারণাটি হ'ল আপনি একটি বাফার তৈরি করেন (নিম্পি অ্যারের জন্য মেমরি বরাদ্দ করুন) এবং পরে এতে যুক্ত হন। ডেটা এবং পুনরুদ্ধার সন্নিবেশ খুব দ্রুত। আপনার প্রয়োজন অনুসারে আমিও এই মডিউলটি তৈরি করেছি। আমার ক্ষেত্রে, আমার কাছে একটি ডিভাইস রয়েছে যা পূর্ণসংখ্যার ডেটা উত্পন্ন করে। আমি ডেটাটি পড়েছি এবং এটি ভবিষ্যতের বিশ্লেষণ এবং প্রক্রিয়াকরণের জন্য বিজ্ঞপ্তি বাফারে রেখেছি।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.