如何在Python中将多维列表最佳地转换为单个项目列表?

时间:2011-07-13 12:56:01

标签: python list optimization recursion

  

可能重复:
  Making a flat list out of list of lists in Python
  Flatten (an irregular) list of lists in Python

输入如下列表:[1,2,[3,4,[5,6,7,[8]]],[9],10]

期望的输出:[1,2,3,4,5,6,7,8,9,10]

目前我有以下递归功能:

def fix_list( li , l = [] ):
    for i in li:
        try:
            len( i )
            fix_list( i, l )
        except:
            l.append( i )
    return l

我觉得try / except catch有点噱头和缓慢,我想知道是否有更好/更优化的方式来执行此任务。所有输入都非常感谢。

5 个答案:

答案 0 :(得分:2)

这是一个迭代版本(最初受Artsiom Rudzenka's启发),它使用切片赋值修改列表,而不是在每次传递中创建新列表。有趣的是,只需要通过列表一次!我对enumerate()的使用有点不正统;我用它来跟踪列表中的索引,当我迭代它时可能会增长,但实际上并没有使用实际的列表项。

def flattened(items, seqtypes=(list, tuple)):

    items = items[:]  # we will return a copy; remove to mutate original
    for i, _ in enumerate(items):
        while isinstance(items[i], seqtypes):
            items[i:i+1] = items[i]
    return items

print flattened([1,2,[3,4,[5,6,7,[8]]],[9],10])

生成器版本:

def flattener(items, seqtypes=(list, tuple)):

    items = items[:]
    for i, _ in enumerate(items):
        while isinstance(items[i], seqtypes):
            items[i:i+1] = items[i]
        yield items[i]

print list(flattener([1,2,[3,4,[5,6,7,[8]]],[9],10]))

这是一个list子类,它有flatten()方法。与sort()reverse()方法一样,这会改变列表并返回None

class listy(list):

    def flatten(self, seqtypes=(list, tuple)):
        for i, _ in enumerate(self):
            while isinstance(self[i], seqtypes):
                self[i:i+1] = self[i]

lst = listy([1,2,[3,4,[5,6,7,[8]]],[9],10])
lst.flatten()
print lst

编辑:我从原始版本中大大简化了这一点。但是,我看到问题已经结束。

答案 1 :(得分:1)

请参阅this answer

def flatten(l):
    for el in l:
        if isinstance(el, collections.Iterable) and not isinstance(el, basestring):
            for sub in flatten(el):
                yield sub
        else:
            yield el

答案 2 :(得分:1)

这是一个简单的生成器:

def flatten(nested):
    for item in nested:
        if isinstance(item, collections.Iterable) and not isinstance(item, basestring):
            for inner_item in flatten(item):
                yield inner_item
        else:
            yield item

不确定它是否“最佳”。

答案 3 :(得分:1)

我在下面尝试过解决方案并且有效:

data = [1,2,[3,4,[5,6,7,[8]]],[9],10]

while any(isinstance(x, list) for x in data):
    tmpLst = []
    for x in data:
        if isinstance(x, list):
            tmpLst.extend(x)
        else:
            tmpLst.append(x)
    data = tmpLst

答案 4 :(得分:0)

另一种方法..

def flatten(old, new):                                                                                                                      
    for i in old:                                                                                                                           
        flatten(i, new) if isinstance(i, list) else new.append(i)                                                                           
    return new                                                                                                                              

if __name__ == '__main__':                                                                                                                  
    l1 = [1, 2, [3, 4, [5, 6, 7, [8]]], [9], 10]                                                                                            
    l2 = list()                                                                                                                             
    l3 = flatten(l1, l2)                                                                                                                     
    print l3

简化,因此您不必向flatten参数列表提供和清空列表..

def rec_flatten(old, new=list()):                                                                                                           
    for i in old:                                                                                                                           
        rec_flatten(i, new) if isinstance(i, list) else new.append(i)                                                                       
    return new                                                                                                                              

if __name__ == '__main__':                                                                                                                  
    l1 = [1, 2, [3, 4, [5, 6, 7, [8]]], [9], 10]                                                                                            
    x = rec_flatten(l1)                                                                                                                     
    print x