【问题标题】:Convert a flat list to list of lists in python将平面列表转换为python中的列表列表
【发布时间】:2012-04-24 20:50:38
【问题描述】:

人们可能想做与扁平列表相反的操作,like here:我想知道如何将扁平列表转换为列表列表。

在 numpy 中,您可以执行以下操作:

>>> a=numpy.arange(9)
>>> a.reshape(3,3)
>>> a
array([[0, 1, 2],
   [3, 4, 5],
   [6, 7, 8]])

我想知道你是如何做到相反的,我通常的解决方案是:

>>> Mylist
['a', 'b', 'c', 'd', 'e', 'f']
>>> newList = []
for i in range(0,len(Mylist),2):
...     newList.append(Mylist[i], Mylist[i+1])
>>> newList 
[['a', 'b'], ['c', 'd'], ['e', 'f']]

有没有更“pythonic”的方式来做到这一点?

【问题讨论】:

  • 最好不要使用list作为变量名,因为有内置函数list()
  • 是的,你是对的,我只是快速编辑代码,我的原始代码看起来不是那样的。

标签: python list


【解决方案1】:
>>> l = ['a', 'b', 'c', 'd', 'e', 'f']
>>> zip(*[iter(l)]*2)
[('a', 'b'), ('c', 'd'), ('e', 'f')]

正如@Lattyware 所指出的,这只有在每次返回元组时zip 函数的每个参数中都有足够的项目时才有效。如果其中一个参数的项目少于其他参数,则项目被切断,例如。

>>> l = ['a', 'b', 'c', 'd', 'e', 'f','g']
>>> zip(*[iter(l)]*2)
[('a', 'b'), ('c', 'd'), ('e', 'f')]

如果是这种情况,那么最好使用@Sven Marnach 的解决方案

How does zip(*[iter(s)]*n) work

【讨论】:

  • 这个解决方案只有在有足够的物品来填充它时才有效,否则物品会被切断。
  • 创建一个生成器,然后复制对它的引用;聪明。
  • @NickT 从技术上讲,它是一个迭代器而不是一个生成器,我不能把它的聪明之处归功于 :)
  • 我看到它有效,但这看起来很可怕而且晦涩难懂。依靠 zip 以这样的顺序访问 iter(l) 的两个副本以产生所需的结果是一个好主意吗??
  • 生成列表列表:map(list,zip(*[iter(l)]*2)),或map(list,zip(*[iter(l)]*3))
【解决方案2】:

这通常使用itertools documentation 中的石斑鱼配方完成:

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

例子:

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list(grouper(2, my_list))
[('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', None)]

【讨论】:

    【解决方案3】:

    如果人们更喜欢列表列表,而不是平面列表中的元组列表,那么可以这样做:

        a = range(20) # sample starting list 
        b = [] # new list
        c = [] # alternate new list
        # ny is length of new list. nx length of each list within it
        nx = 5; ny = 4 
        bb = 0; ee = bb + nx # option one: sliding indeces for slices.
        for ii in range(ny-1):
            bb += nx
            ee += nx
            b.append(a[bb:ee])
            c.append(a[slice(ii*nx,nx*(ii+1))]) # option two, use slice()
    

    (我已经尝试将整个 for 循环缩小为带有列表理解的一行,但没有成功。按照我使用它的方式, slice() 几乎可以让你到达那里。) 这些方法相对于其他提到的其他方法的一个可能优势是,如果您的原始平面列表不是您的新的、所需列表的维度的偶数倍,您将不会丢失任何数据。需要注意的是,最后一个列表将比所有其他列表短,因为它将包含“剩菜”。当然,这些方法都没有让我觉得非常 Pythonic。

    【讨论】:

    • 我不明白你为什么在第二种方法中使用slice(),而不是切片语法。进行计算并不意味着您不能使用a[ii*nx:nx*(ii+1)] 或其他任何东西。
    【解决方案4】:

    另一种创建列表列表的方法可以简化如下:

    >>>MyList = ['a','b','c','d','e','f']
    # Calculate desired row/col
    >>>row = 3
    >>>col = 2
    >>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)]
    >>>NewList
    [['a', 'b', 'c'], ['d', 'e', 'f']]
    

    此方法可以扩展为产生任何行和列大小。如果选择行和列值,例如row*col >len(MyList),则包含MyList 中最后一个值的子列表(行)将在那里结束,NewList 将简单地填充适当数量的空列表以满足行/ col规格

    >>>MyList = ['a','b','c','d','e','f','g','h']
    >>>row = 3
    >>>col = 3
    >>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)]
    >>>NewList
    [['a', 'b', 'c'], ['d', 'e', 'f'], ['g','h']]
    
    >>>row = 4
    >>>col = 4
    >>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)]
    [['a', 'b', 'c', 'd'], ['e', 'f', 'g','h'], [], []]
    

    【讨论】:

    • 我想这应该是公认的答案,因为问题是要求列表列表而不是元组列表。或者罗伯特在上面的评论中的回答。
    猜你喜欢
    • 2020-01-26
    • 1970-01-01
    • 2019-05-26
    • 2016-07-05
    • 1970-01-01
    • 2018-01-17
    • 2022-11-23
    • 2012-05-24
    • 2014-02-16
    相关资源
    最近更新 更多