2017-11-10 114 views
2

我想弹出collections.deque左边最多的limit项。从Python中的双端队列左边弹出一个最多N个条目

def popAll(q, limit=None): 
    if limit is None: 
     result = list(q) 
     q.clear() 
    else: 
     result = [] 
     try: 
      for _ in xrange(limit): 
       result.append(q.popleft()) 
     except IndexError: 
      pass 
    return result 

这似乎工作,但似乎......笨重。有没有更“pythonic”的方式? deque对象不支持切片。

注:我的目的,因为我将要包装一个threading.RLock()访问内部访问deque的,我不需要一个固有的线程安全的答案。

+0

当您执行此操作时是否有其他线程正在从此双端队列中读取或写入数据?您是否希望多流行操作从其他读者的角度来看是原子的? –

+0

我不需要线程安全;我正在用'threading.RLock'来包装它。 –

回答

1

这里是我怎么可能做到这一点:

def popAll(q, limit=None): 
    return [q.popleft() for _ in xrange(min(limit or sys.maxsize, len(q)))] 

或者,也许是这样的:

def popAll(q, limit=None): 
    if limit is None: 
     limit = sys.maxsize 
    return [q.popleft() for _ in xrange(min(limit, len(q)))] 

注意这两个例子中的popAll(q, 0)中的行为。在第一个例子中,它返回整个队列。第二,它返回一个空的列表。

+0

'xrange'? (这是Python 2) –

+0

这是一个很好的观点。我会改变它。 –

+0

此外,您还需要记录'popA​​ll(q,0)'的行为,该行为在我的答案和问题中的代码之间有所不同。 –

1

如果它是一个迭代,您可以使用itertools.islice然后取出:

from itertools import islice 

def popAll(q, limit=None): 
    result = list(islice(q, limit)) 
    if limit is None or limit >= len(q): 
     q.clear() 
    else: 
     for _ in range(limit): 
      q.popleft() 
    return result 

万一limit因此不None,我们首先计算我们可以删除(这是最低的项目数q中的项目数量和限制)。在limitNone或大于或等于零的情况下,简单地clear() deque更有效,否则我们遍历元素并一次删除它们。

+0

我说这是一个双向转换,而不是一个不支持切片的列表。 –

+0

@JasonS:我想出了一个更好的主意,它使用迭代切片(可用于所有迭代)。 –

相关问题