将列表项追加到列表列表中

时间:2017-12-21 17:05:39

标签: python python-3.x list

我有list,其结构如下:

data = [[], [], ..., []]  # N sub-lists

我从以下格式无法控制的流程中接收数据:

new_entries = ['foo', 'bar', ..., 'foobar']  # guaranteed N entries

new_entries的i th 子列表中存储data的i th 项的最佳方法是什么?吗

所以一次到达后的结果将是:

data = [['foo'], ['bar'], ..., ['foobar']]

以下内容是否合适?

for i, item in enumerate(new_entries):
    data[i].append(item)

2 个答案:

答案 0 :(得分:3)

使用zip似乎比enumerate更优雅,但通常您的代码没有任何问题。对于任何人必须阅读或维护的任何生产级代码,这个(或你的)应该是要走的路:

for lst, entry in zip(data, new_entries):
    lst.append(entry)

如果你觉得在一行中做这种病的冲动,你可以使用map或理解:

list(map(lambda x: x[0].append(x[1]), zip(data, new_entries)))  # Py3
map(lambda (x, y): x.append(y), zip(data, new_entries))  # Py2

# or shorter, thx to Stefan Pochmann:
# Py3: any as a more space-efficient consumer than list
any(map(list.append, data, new_entries))  
map(list.append, data, new_entries)  # Py2

[lst.append(entry) for lst, entry in zip(data, new_entries)]

但我强烈建议不要牺牲保存线的可读性。在这两种情况下,data中列表的突变更多的是副作用!

当然,可以使用一个很好的旧列表理解(实际上使用理解的结果),但是由于连接是O(M+N)而出现性能问题:

data = [lst + [entry] for lst, entry in zip(data, new_entries)]

答案 1 :(得分:1)

如果data的长度与new_entries相同,那么您只能将每个项目封装在列表中:

new_entries = ['foo', 'bar', ..., 'foobar']
final_entries = [[i] for i in new_entries]

要随时添加新数据,您可以使用以下类:

class Stream:
   def __init__(self):
       pass
   def __setitem__(self, name, stream):
        self.__dict__[name] = map(lambda x:[x], stream) if name not in self.__dict__ else [d+[b] for d, b in zip(self.__dict__[name], stream)]
   def __getitem__(self, name):
        return self.__dict__[name]
   def __repr__(self):
        return "{}({})".format(self.__class__.__name__, ', '.join("{}:{}".format(a, str(list(b))) for a, b in self.__dict__.items()))

stream = Stream()
stream['first'] = ['foo', 'bar', 'foobar']
print(stream.first)
>>>[['foo'], ['bar'], ['foobar']]
stream['first'] = ['foobar', 'newfoo', 'anotherfoo']
print(stream.first)
>>>[['foo', 'foobar'], ['bar', 'newfoo'], ['foobar', 'anotherfoo']]