Reputation: 744
I have a generator:
def get_items(self):
for item in self.info.get_data():
item = {
'_name': item.name,
'_email': item.email,
}
yield item
I want to iterate over this generator, assign index to each item key, and then store them in a dict like so:
items = ['item_0_name': 'example name', 'item_0_email': '[email protected]',
'item_1_name': 'Some name', 'item_1_email': '[email protected]' ....]
I use enumerate to get index, but then I can't access item's key to add index to it:
items = []
for i, item in enumerate(self.get_items()):
items['item_'.join(str(i)).join(self.get_items()[i])] = item
But then I'm getting:
TypeError: 'generator' object has no attribute '__getitem__
Is there any Pythonic way to do this?
Upvotes: 1
Views: 470
Reputation: 12077
Try the following:
items = []
for i, item in enumerate(self.get_items()):
items.append({'item_{}{}'.format(i, k): v for k, v in item.iteritems()})
List demo:
In [54]: for i, j in enumerate(get_items(test)):
items.append({'item_{}{}'.format(i, k): v for k, v in j.iteritems()})
....:
In [55]: items
Out[55]:
[{'item_0_email': '[email protected]', 'item_0_name': 'example_name'},
{'item_1_email': '[email protected]', 'item_1_name': 'Some name'}]
I assume that what you actually want to do is to append these dictionaries to a list, because, well, items
is defined as a list. Otherwise if you want to add these to a dictionary, do the following:
items = {} # Items is now a dictionary
for i, item in enumerate(self.get_items()):
items.update({'item_{}{}'.format(i, k): v for k, v in item.iteritems()})
Dictionary demo
In [56]: items = {}
In [57]: for i, j in enumerate(get_items(test)):
items.update({'item_{}{}'.format(i, k): v for k, v in j.iteritems()})
....:
In [58]: items
Out[58]:
{'item_0_email': '[email protected]',
'item_0_name': 'example_name',
'item_1_email': '[email protected]',
'item_1_name': 'Some name'}
Remember that self.get_items()
yields dictionaries. That means you'll have to deal with all of the items in the dictionary. And the above methods are doing exactly that.
The code uses dict comprehensions
. They are like list comprehensions but, in this case, iterate over the keys and values of the each dictionary that the self.get_items()
generator yields.
Upvotes: 3
Reputation: 2822
The error you get is due to the fact that self.get_items()
is a generator, and such objects do not permit to do such thing as self.get_items()[1]
because in terms of meaning, there is no history.
But in your case, you just missed that self.get_items()
yields one dict at each call. You just have to make use of that dict:
items = []
for i, item_dict in enumerate(self.get_items()):
for key, item in item_dict:
items['item_{0}{1}'.format(i, key)] = item
By the way, you have another strong error (that I did not correct in my example above): items
is a list, so your attempt to do items[some_not_yet_defined_string] = something
will fail, first because the index is of str
type, and second because you cannot append stuff to list by specifying new indexes.
Moreover, your call to 'item_'.join(str(i)).join [...]
is not what you expect: str.join(iterable)
returns a string made of the iterable items separated by the given str
. It's not generating multiple strings, and will surely not generate several keys for your items
dict.
Upvotes: 2