Ma0
Ma0

Reputation: 15204

Appending list items into a list of lists

I have a list which has the following structure:

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

I am receiving data from a process over which I have no control in the following format:

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

What is the best way to have the ith item of the new_entries stored in the ith sublist of data?

So that the result after one arrival would be:

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

Is the following as good as it gets?

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

Upvotes: 2

Views: 88

Answers (2)

Ajax1234
Ajax1234

Reputation: 71451

If the length of data is the same as new_entries, then you can merely encapsulating each item in a list:

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

To add new data at any time, you can use a class:

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']]

Upvotes: 1

user2390182
user2390182

Reputation: 73450

Using zip seems a little more elegant than enumerate, but generally there is nothing wrong with your code. For any production-level code that anybody will ever have to read or maintain, this (or yours) should be the way to go:

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

If you feel the pathologic urge to do it in one line, you could use map or a comprehension:

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)]

but I would strongly recommend not sacrificing readability for saving lines. In both cases the mutation of the lists in data is more of a side effect!

And, of course, a good old list comprehension (that actually uses the result of the comprehension) can be used but does come with performance issues as the concatenation is O(M+N):

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

Upvotes: 3

Related Questions