文档章节

迭代访问列表的最“ pythonic”方法是什么?

j
 javail
发布于 01/26 20:02
字数 1298
阅读 65
收藏 0

我有一个Python脚本,它将一个整数列表作为输入,我需要一次处理四个整数。 不幸的是,我无法控制输入,或者将其作为四元素元组的列表传递。 目前,我正在以这种方式对其进行迭代:

for i in xrange(0, len(ints), 4):
    # dummy op for example code
    foo += ints[i] * ints[i + 1] + ints[i + 2] * ints[i + 3]

不过,它看起来很像“ C思维”,这使我怀疑还有一种处理这种情况的更Python的方法。 该列表在迭代后被丢弃,因此不需要保留。 也许这样的事情会更好?

while ints:
    foo += ints[0] * ints[1] + ints[2] * ints[3]
    ints[0:4] = []

不过,还是不太“正确”。 :-/

相关问题: 如何在Python中将列表分成均匀大小的块?


#1楼

此问题的理想解决方案适用于迭代器(而不仅仅是序列)。 它也应该很快。

这是itertools文档提供的解决方案:

def grouper(n, iterable, fillvalue=None):
    #"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.izip_longest(fillvalue=fillvalue, *args)

在Mac book air上使用ipython的%timeit ,每个循环可获得47.5美元。

但是,这对我来说真的不起作用,因为结果被填充为甚至大小的组。 没有填充的解决方案稍微复杂一些。 最幼稚的解决方案可能是:

def grouper(size, iterable):
    i = iter(iterable)
    while True:
        out = []
        try:
            for _ in range(size):
                out.append(i.next())
        except StopIteration:
            yield out
            break

        yield out

简单但很慢:每个循环693 us

我能想到的最佳解决方案是将islice用于内部循环:

def grouper(size, iterable):
    it = iter(iterable)
    while True:
        group = tuple(itertools.islice(it, None, size))
        if not group:
            break
        yield group

使用相同的数据集,每个循环可获得305 us。

无法以比这更快的速度获得纯解决方案,我为以下解决方案提供了一个重要的警告:如果输入数据中包含filldata实例,则可能会得到错误的答案。

def grouper(n, iterable, fillvalue=None):
    #"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    for i in itertools.izip_longest(fillvalue=fillvalue, *args):
        if tuple(i)[-1] == fillvalue:
            yield tuple(v for v in i if v != fillvalue)
        else:
            yield i

我真的不喜欢这个答案,但是速度更快。 每个循环124 us


#2楼

另一个答案,其优点是:

1)容易理解
2)适用于任何可迭代的对象,而不仅仅是序列(上面的某些答案会在文件句柄上阻塞)
3)不会一次将块全部加载到内存中
4)不在内存中对同一迭代器建立一个大块的引用列表
5)列表末尾不填充填充值

话虽如此,我还没有计时,所以它可能比一些更聪明的方法要慢,并且某些优点可能与用例无关。

def chunkiter(iterable, size):
  def inneriter(first, iterator, size):
    yield first
    for _ in xrange(size - 1): 
      yield iterator.next()
  it = iter(iterable)
  while True:
    yield inneriter(it.next(), it, size)

In [2]: i = chunkiter('abcdefgh', 3)
In [3]: for ii in i:                                                
          for c in ii:
            print c,
          print ''
        ...:     
        a b c 
        d e f 
        g h 

更新:
由于内循环和外循环从同一个迭代器中提取值,因此带来了一些缺点:
1)Continue在外部循环中无法按预期工作-它只是继续到下一个项目,而不是跳过一个块。 但是,这似乎不是问题,因为在外循环中没有要测试的东西。
2)break在内部循环中无法正常工作-控件将在迭代器中的下一个项目中再次进入内部循环。 要跳过整个块,可以将内部迭代器(上面的ii)包装在一个元组中,例如for c in tuple(ii)中将for c in tuple(ii)打包,或者设置一个标志并耗尽迭代器。


#3楼

与其他建议类似,但不完全相同,我喜欢这样做,因为它简单易读:

it = iter([1, 2, 3, 4, 5, 6, 7, 8, 9])
for chunk in zip(it, it, it, it):
    print chunk

>>> (1, 2, 3, 4)
>>> (5, 6, 7, 8)

这样,您将不会得到最后的部分块。 如果要获取(9, None, None, None)作为最后一块,只需使用itertools izip_longest


#4楼

使用小功能和事情确实对我没有吸引力。 我更喜欢只使用切片:

data = [...]
chunk_size = 10000 # or whatever
chunks = [data[i:i+chunk_size] for i in xrange(0,len(data),chunk_size)]
for chunk in chunks:
    ...

#5楼

我需要一个可以与集合和生成器一起使用的解决方案。 我无法提出任何简短而又漂亮的内容,但至少可以理解。

def chunker(seq, size):
    res = []
    for el in seq:
        res.append(el)
        if len(res) == size:
            yield res
            res = []
    if res:
        yield res

清单:

>>> list(chunker([i for i in range(10)], 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

组:

>>> list(chunker(set([i for i in range(10)]), 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

发电机:

>>> list(chunker((i for i in range(10)), 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

本文转载自:https://fi.sofbug.com/question/1oyd

j
粉丝 5
博文 1144
码字总数 0
作品 0
深圳
私信 提问
对比几段代码,看看你是 Python 菜鸟还是老鸟

Python 里有个小彩蛋: 在 Python Shell 里输入 这段话被称作“Python 之禅”(The Zen of Python),它列举了一些 Python 所推崇的理念,比如: 优美胜于丑陋 明确胜于隐晦 简单胜于复杂 …...

crossin
2019/03/05
109
0
Pythonic到底是什么玩意儿?

这是几个月前在 EuroPython 邮件列表(主要用来组织和计划 EuroPython 会议的邮件列表)出现的问题。这是一个非常有意思的问题,我看到这个词被无数次地使用,但鲜有人尝试解释它的含义。在这...

陶邦仁
2013/01/15
442
2
python-进阶-优雅的python写法

Python 这门语言最大的优点之一就是语法简洁,好的代码就像伪代码一样,干净、整洁、一目了然。但有时候我们写代码,特别是 Python 初学者,往往还是按照其它语言的思维习惯来写,那样的写法...

时间之友
2017/11/22
0
0
一些Python的惯用法和小技巧:Pythonic

Pythonic其实是个模糊的含义,没有确定的解释。网上也没有过多关于Pythonic的说明,我个人的理解是更加Python,更符合Python的行为习惯。本文主要是说明一些Python的惯用法和小技巧,其实与上...

熟悉的防守
2016/03/29
39
0
Python 集合是什么,为什么应该使用以及如何使用?

Python 配备了几种内置数据类型来帮我们组织数据。这些结构包括列表、字典、元组和集合。 根据 Python 3 文档: 集合是一个无序集合,没有重复元素。基本用途包括成员测试和消除重复的条目。...

05%
2018/07/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

LiteOS云端对接教程10-LiteOS使用NB模组基于LWM2M对接华为OC平台实战

1. 在云端添加测试设备 打开之前教程新建的LWM2M产品,进入设备管理界面新建真实设备,设备标识符要填写NB模组的IMEI号,可以使用如下命令查看: AT+CGSN=1 测试结果如下: +CGSN:86772503...

小熊派开源社区
15分钟前
32
0
多团队基于git代码管理协作流程

多团队git协同开发流程 一、版本管理的挑战 虽然有这么优秀的版本管理工具,但是我们面对版本管理的时候,依然有非常大得挑战,我们都知道大家工作在同一个仓库上,那么彼此的代码协作必然带...

kingbox2016
16分钟前
42
0
Elmedia Video Player Pro for Mac(苹果万能视频播放器) v7.9中文版

mac电脑用哪款视频播放器最合适呢?elmedia video player pro Mac版是适用于Mac OS的视频播放器。它可以播放几乎任何文件类型,无论是AVI,MP4,FLV,WMV,MKV,MP3,M4V等.Elmedia Video Pl...

云不若
21分钟前
57
0
11个默克尔树开源项目

Merkle树是一种可以有效验证部分数据存在于指定数据集并且未被篡改的高效的哈希树结构,作为一种底层技术广泛应用在各种区块链的实现当中,对于商品溯源、知识产权确认、区块链公证等区块链应...

区块链教程
48分钟前
64
0
Linux系统运维工程师入门绝招放送

运维是干嘛的?安装服务器系统?重装系统再装系统?背锅的? 我就稀里糊涂的,这样报着必死的决心,考下RHCE认证,走上了Linux运维的道路,成为了一名linux运维工程师。有些心得跟大家分享下...

linuxprobe2020
52分钟前
64
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部