复制嵌套列表并用连续的数字填充

时间:2019-01-23 13:09:08

标签: python

给出此嵌套列表:

foo = [["apple", "cherry"], ["banana"], ["pear", "raspberry", "pineapple"]]

我想保留结构并将所有项目替换为连续的数字。我想要的输出是:

[[0, 1], [2], [3, 4, 5]]

我希望有一个简单的单线飞机,但是我想到的最短的可行解决方案是:

foo_numbers = []
count = 0

for i, sublist in enumerate(foo):
    foo_numbers.append([])
    for item in sublist:
        foo_numbers[i].append(count)
        count += 1

通常,这些手动迭代器表明,有更多的Python方式可以实现相同的目的。如果要使用列表解析来完成此操作,我将看不到如何为两个循环组成一个“共享计数器”,因此它不会从每个sublist的零开始。

4 个答案:

答案 0 :(得分:5)

您可以将itertools.count与嵌套列表理解结合使用:

from itertools import count

foo = [["apple", "cherry"], ["banana"], ["pear", "raspberry", "pineapple"]]

c = count()  # 0 start is default, e.g. count(1) will start from 1
res = [[next(c) for _ in lst] for lst in foo]

print(res)
# [[0, 1], [2], [3, 4, 5]]

答案 1 :(得分:2)

比较这些解决方案:

import itertools

def f1(foo):
    """original version in question"""
    foo_numbers = []
    count = 0
    for i, sublist in enumerate(foo):
        foo_numbers.append([])
        for item in sublist:
            foo_numbers[i].append(count)
            count += 1
    return foo_numbers

def f2(foo):
    """@jpp answer"""
    c = itertools.count()
    return [[next(c) for _ in range(len(lst))] for lst in foo]

def f3(foo):
    """@DanielMesejo answer"""
    foo_numbers = []
    count = 0
    for i, sublist in enumerate(foo):
        foo_numbers.append([j for j in range(count, len(sublist) + count)])
        count += len(sublist)
    return foo_numbers

给我们这个:

>>> import timeit
>>>
>>> timeit.timeit('f(foo)', 'from __main__ import f1 as f, foo')
1.2990377170499414
>>> timeit.timeit('f(foo)', 'from __main__ import f2 as f, foo')
2.260929798008874
>>> timeit.timeit('f(foo)', 'from __main__ import f3 as f, foo')
2.1552230638917536

似乎原始版本的速度更快(提高了2倍)。

答案 2 :(得分:2)

您可以使用list comprehension代替内部循环:

foo = [["apple", "cherry"], ["banana"], ["pear", "raspberry", "pineapple"]]

foo_numbers = []
count = 0

for i, sublist in enumerate(foo):
    foo_numbers.append([j for j in range(count, len(sublist) + count)])
    count += len(sublist)

print(foo_numbers)

输出

[[0, 1], [2], [3, 4, 5]]

通常,列表理解比列表创建循环要快。或者,您可以将范围对象转换为列表,如下所示:

foo_numbers.append(list(range(count, len(sublist) + count)))

答案 3 :(得分:0)

如果您确实do not要导入任何内容,请使用以下给定的解决方案:

foo = [["apple", "cherry"], ["banana"], ["pear", "raspberry", "pineapple"]]

count = -1

def indexer(fruits):
    global count
    count += 1
    return count


foo_new = list(map(lambda fruits: list(map(indexer, fruits)), foo))

print(foo_new)              

输出:

[[0, 1], [2], [3, 4, 5]]