代码之家  ›  专栏  ›  技术社区  ›  offeltoffel

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

  •  2
  • offeltoffel  · 技术社区  · 6 年前

    给定此嵌套列表:

    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
    

    通常,这些手动迭代器指示有一种更为蟒蛇式的方法来实现相同的事情。如果要用列表理解来完成这项工作,我不知道如何为两个循环组成一个“共享计数器”,因此它不会从零开始 sublist .

    4 回复  |  直到 6 年前
        1
  •  5
  •   Kim    6 年前

    你可以使用 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]]
    
        2
  •  2
  •   Dani Mesejo    6 年前

    你可以使用 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]]
    

    一般来说,列表理解比列表创建的循环要快。另一种方法是将range对象转换为列表,如下所示:

    foo_numbers.append(list(range(count, len(sublist) + count)))
    
        3
  •  2
  •   Ralf    6 年前

    比较这些解决方案:

    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倍)。

        4
  •  0
  •   BlackBeard    6 年前

    如果你真的 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]]