List Pythonic方法返回较大列表中每n个项目的列表

List Pythonic方法返回较大列表中每n个项目的列表,list,python,List,Python,假设我们有一个从0到1000的数字列表。是否有一种通灵的/有效的方法来生成第一项和其后每一项的列表,即[0,10,20,30,…] 是的,我可以使用for循环来实现这一点,但我想知道是否有更简洁的方法来实现这一点,甚至是在一行中 >>> lst = list(range(165)) >>> lst[0::10] [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]

假设我们有一个从0到1000的数字列表。是否有一种通灵的/有效的方法来生成第一项和其后每一项的列表,即
[0,10,20,30,…]

是的,我可以使用for循环来实现这一点,但我想知道是否有更简洁的方法来实现这一点,甚至是在一行中

>>> lst = list(range(165))
>>> lst[0::10]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
请注意,这比循环和检查每个元素的模数快100倍左右:

$ python -m timeit -s "lst = list(range(1000))" "lst1 = [x for x in lst if x % 10 == 0]"
1000 loops, best of 3: 525 usec per loop
$ python -m timeit -s "lst = list(range(1000))" "lst1 = lst[0::10]"
100000 loops, best of 3: 4.02 usec per loop

列表的理解正是为了:

smaller_list = [x for x in range(100001) if x % 10 == 0]
您可以在python官方文档中获得关于它们的更多信息:

您可以像这样使用切片操作符:

l = [1,2,3,4,5]
l2 = l[::2] # get subsequent 2nd item

从手动:
s[i:j:k]步骤k从i到j的s切片

li = range(100)
sub = li[0::10]

>>> sub
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

这将挑选出列表中的每10个元素。

下面是“每10个项目”列表理解的更好实现,它不使用列表内容作为成员资格测试的一部分:

>>> l = range(165)
>>> [ item for i,item in enumerate(l) if i%10==0 ]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
>>> l = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
>>> [ item for i,item in enumerate(l) if i%10==0 ]
['A', 'K', 'U']

但这仍然比仅使用列表切片慢得多。

为什么不同时使用范围函数的步长参数来获得:

l = range(0, 1000, 10)
作为比较,在我的机器上:

H:\>python -m timeit -s "l = range(1000)" "l1 = [x for x in l if x % 10 == 0]"
10000 loops, best of 3: 90.8 usec per loop
H:\>python -m timeit -s "l = range(1000)" "l1 = l[0::10]"
1000000 loops, best of 3: 0.861 usec per loop
H:\>python -m timeit -s "l = range(0, 1000, 10)"
100000000 loops, best of 3: 0.0172 usec per loop
  • source\u list[::10]
    是最明显的,但这不适用于任何iterable,对于大型列表来说也不具有内存效率
  • itertools.islice(source_sequence,0,None,10)
    适用于任何iterable,并且内存效率高,但对于大列表和大步进来说可能不是最快的解决方案
  • (源列表[i]表示xrange中的i(0,len(源列表),10))

  • 上限应该是1000,而不是10000。您的解决方案不包括1000的上限,因为范围在999处停止+1用于列表理解的链接。这实际上并不是每10项提取一次,而是提取每个值可被10整除的项。在这个特定的例子中,它是相同的,但可能不是。当然,列表理解通常更强大。OTOH,这个问题假设了一个现有的列表,在这种情况下,一个切片就可以了。我在下面的列表理解答案中对此进行了评论。注意“如果x%10==0”。它只适用于这个特定的列表示例,但是如果输入列表是例如l=range(01000,2),它不会每10项就提取一次。@Andre:非常正确。这是一个简陋的语言特性的例子,切片操作符,在本例中,(1)使它更容易得到正确的结果;(2) 使表达更加简洁;(3)正好快了2个数量级。(1) 当然,这是到目前为止最重要的关注点,但是,由于该语言的精心设计和实现,您可以以1的价格获得所有这三种语言。很好的问题和回答。
    0
    l[0::10]
    中是多余的
    l[::10]
    更具可读性,更少混乱。您的比较不合适,因为您选择的是每一个可被10整除的元素,而不是每10个元素。比较切片表示法更合适:
    lst=list(范围(1000));lst1=[lst[i]表示范围内的i(0,len(lst),10)]
    。在我的机器上,我得到了“1000000个循环,最好的5:395纳秒/循环”作为切片表示法,以及“20000个循环,最好的5:11.1 usec/循环”作为列表理解。当范围(0,1001,10)已经只取每10个元素时,为什么有if子句?这里的注释相同,这并不能解决更普遍的问题“以Pythonic方式返回较大列表中每个第n项的列表”您的解决方案取决于这样一个事实,即示例列表的值为0到1000,并且只从列表中拉出值可被10整除的项,而不是每10项。OP写道:“我们有一个从0到1000的数字列表所以他不需要一个通用的解决方案。他写了‘假设我们有……’,这意味着这只是一个例子。如果他真的想要从0到1000的列表中每隔10个数字,那么答案应该是range(01001,10)或类似的东西。@SilentGhost:没错,但由于这是一个初学者的问题,range函数可能是他们真正想要做的,所以我认为这是一个有效的答案。(虽然上限应该是1001,而不是1000)+1最佳答案,国际海事组织。所有三个建议都是一个通用解决方案(即,以源列表为给定)。生成器解决方案(3)很好,因为它在源列表的索引上进行过滤。它的内存效率可能和2一样高。索引和结果列表都是生成器,因此是惰性构造的,如果不需要在单个块中使用结果列表,这可能也是最快的。只有当源列表可以是生成器时,我才会使用Paul的“item,I in enumerate(l)”成语,因为没有生成器的len()。顺便问一下,哪种iterable不能与1一起使用。?发电机?!Iterable=object with_uuuiter_uuuuu()方法返回迭代器(object with next()方法)如何从第三个开始获取第二个项目?@user1993
    L[2::2]
    l = range(0, 1000, 10)
    
    H:\>python -m timeit -s "l = range(1000)" "l1 = [x for x in l if x % 10 == 0]"
    10000 loops, best of 3: 90.8 usec per loop
    H:\>python -m timeit -s "l = range(1000)" "l1 = l[0::10]"
    1000000 loops, best of 3: 0.861 usec per loop
    H:\>python -m timeit -s "l = range(0, 1000, 10)"
    100000000 loops, best of 3: 0.0172 usec per loop