Python:以指定格式打印列表中的列表

3

我有一个列表嵌套列表,l = [['a','b', 'c'], 'd','e', ['f', 'g']]。列表元素并不总是字母。

现在,我使用了下面的代码:

>>> index =1
>>> for i in l:
...     if isinstance(i, list):
...             for j in i :
...                     print index, j
...                     index = index + 1
...     else:
...             print index, i
...             index = index + 1
... 
1 a
2 b
3 c
4 d
5 e
6 f
7 g

你可以看到我打印结果的格式。 另一个例子:
l = [['aaa','bbb','xxx'], 'ddd']

Output = 

1 aaa
2 bbb
3 xxx
4 ddd

我的问题是是否有更好的方法来做这件事或者Python中是否有内置函数。
PS:列表只会嵌套一层。因此,[ [a, [b,c] ], d, e ] 不可能出现。

1
值得问的一件事是,你是否真的想以这种方式保存数据。换句话说,你如何获得一个包含列表和字符串的列表?通常,如果你可以统一事物,使得你的列表只保存一种数据类型,那么会更容易些。 - mgilson
@mgilson: 让我举个例子,假设我有一个单词列表 ['w1','w2','w3'],现在我创建了一个函数 get_meanings(word),它将返回传递为参数的单词的含义。然后我使用 map(get_meanings, words),这将返回上述形式的输出,因为如果一个单词有多个可用的含义,API会返回一个list - ronnie
1
@ronnie 最好的解决方案是让函数返回长度为一的列表,以便在获得结果时更容易处理。 - Gareth Latty
@Lattyware:你能否以更详细的形式解释一下? - ronnie
1
@ronnie,目前你的get_meanings(word)返回["meaning1", "meaning2"],表示有多个含义,或者返回"meaning",表示只有一个含义。我的建议是,在第二种情况下让它返回["meaning"],这样就不需要特殊处理了。 - Gareth Latty
显示剩余2条评论
2个回答

7

您可以使用itertools.chain.from_iterable()enumerate()轻松完成此操作:

>>> import itertools
>>> l = [['a','b', 'c'], 'd','e', ['f', 'g']]
>>> for index, value in enumerate(itertools.chain.from_iterable(l), 1):
...     print(index, value)
... 
1 a
2 b
3 c
4 d
5 e
6 f
7 g

编辑:正如mgilson指出的那样,这在顶层作为多字符字符串元素时效果不佳。我认为最好的解决方案是像他在答案中所做的那样使用生成器,但我认为字符串是特殊情况,而不是列表,因此我会反转逻辑:

def flatten(seq):
    for item in seq:
        if not isinstance(item, str): #Use `basestring` in 2.x
            yield from item
            #For Python <3.3
            #for subitem in item:
            #    yield subitem
        else:
            yield item

1
这对于以下形式的列表不太适用:l = [['aa','b', 'c'], 'dd','e', ['ff', 'g']](中间的 dd 被分成了 2 个元素)。 - mgilson
@mgilson 非常正确,我没有想到那个。 - Gareth Latty
在py2k中,您可能希望使用isinstance(item,basestring)来捕获Unicode字符串。 - mgilson
@mgilson 另一个好观点。我不经常使用2.x来考虑那个。感谢你的所有发现。 - Gareth Latty
@mgilson 这使得这种迭代器看起来更加舒适。 - Gareth Latty
显示剩余2条评论

6
我会创建一个生成器来展平列表:
def flatten(lst):
   for i in lst:
       if(isinstance(i,list)):
          for x in i:
              yield x
       else:
           yield x

然后我会使用 enumerate 进行打印:

for idx,item in enumerate(flatten(lst),1):
    print idx,item

很好,我之前不知道 Python 中有 generator - ronnie
如果有变量嵌套,我会这样做。对于最多一层嵌套来说,这似乎有点过度设计了。 - inspectorG4dget
1
@inspectorG4dget 我完全不同意,用这种方式编写代码可以使其更易读和清晰。 - Gareth Latty
@Lattyware:对于一个<=1级嵌套列表,链式编程更加简单。如果嵌套级别<=n,n>1,则不仅需要展平,而且还使其更易读。只要程序员知道什么是链式编程,我认为链式编程更易读。但也许这是一个主观的事情。 - inspectorG4dget
1
@inspectorG4dget -- “chaining” 的问题在于字符串是可迭代的。因此,如果您在顶层有一个字符串“foobar”,当您“链”它时,您最终会得到 ...,'f','o','o','b','a','r',...。否则,我同意这里使用“链”的方式。我想你可以这样做:for x in it.chain(*([x] if isinstance(x,basestring) else x for x in lst)):,但在我看来,这开始变得非常难以阅读了... - mgilson
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接