How to make an index combining values of lists nested in tuples?
Solution 1
You can use dictionary to construct the list
my_list = [('a',[0]), ('b',[1]), ('c',[2]), ('a',[3])]
my_dict = {}
for item in my_list:
if item[0] in my_dict.keys():
### if key exists append to list
my_dict[item[0]].extend(item[1][0:])
else:
### if key does not exist create new key-value pair
my_dict[item[0]] = [item[1][0]]
my_list = my_dict.items()
print my_list
Solution 2
This seems very simple using an OrderedDict
(import collections
first):
In [438]: dict_ = collections.OrderedDict()
In [439]: for l in my_list:
...: dict_.setdefault(l[0], []).extend(l[1])
...:
In [440]: dict_
Out[440]: OrderedDict([('a', [0, 3]), ('b', [1]), ('c', [2])])
Now if you want to get your tuples back just iterate over the dictionary:
In [441]: [(k, v) for k, v in dict_.items()]
Out[441]: [('a', [0, 3]), ('b', [1]), ('c', [2])]
Solution 3
You can use the defaultdict
container to create a dictionary of lists, then just store the value of each tuple pair. Note that I extend your original list with the item ('d', [4, 5])
to illustrate that this method also works with a list of arbitrary length.
from collections import defaultdict
my_list = [('a', [0]), ('b', [1]), ('c', [2]), ('a', [3]), ('d', [4, 5])]
dd = defaultdict(list)
for pair in my_list:
k, v = pair
dd[k].extend(v)
>>> dd.items()
[('a', [0, 3]), ('c', [2]), ('b', [1]), ('d', [4, 5])]
Related videos on Youtube
Etsaf
Updated on December 03, 2022Comments
-
Etsaf over 1 year
I'm having a hard time achieving what I need to achieve so I was wondering if someone here could help me :-)
I've seen the example 11.4. (List membership) on http://openbookproject.net/thinkcs/python/english3e/lists.html and it's quite close to my goal in some ways.
The project is:
-
Starting with a list of tuples refering to (key, [list of values])
my_list = [('a',[0]), ('b',[1]), ('c',[2]), ('a',[3])]
-
I'd like to scan 'my_list' in order to append the nested lists, combining the lists of values for only one key, which would look like this :
my_list = [('a',[0, 3]), ('b',[1]), ('c',[2])]
I succeeded to combine values manually but I'd like to automate it and I can't find how to do so! ^^
-
For now, here is what I've got :
# my_input == 'a b c a' #splitting input to list >>> raw_list = my_input.split() >>> raw_list ['a', 'b', 'c', 'a'] #getting an enumeration for each entry #### (in order of appearance, this is important!) #### >>> enum_list = [(b,[a]) for a, b in enumerate(raw_list)] >>> enum_list [('a', [0]), ('b', [1]), ('c', [2]), ('a', [3])] #trying to append the enum value of the second 'a' to the first tuple of 'a' >>> for (x, y) in enum_list : ... for (x, z) in enum_list : ... enum_list[enum_list.index((x, z))][1].append(y) ... >>> enum_list [('a', [0, [...], [1, [...], [...], [2, [...], [...], [...], [3, [...], [...], [...], [...]]], [3, [...], [...], [2, [...], [...], [...], [...]], [...]]], [2, [...], [1, [...], [...], [...], [3, [...], [...], [...], [...]]], [...], [3, [...], [1, [...], [...], [...], [...]], [...], [...]]], [3, [...], [1, [...], [...], [2, [...], [...], [...], [...]], [...]], [2, [...], [1, [...], [...], [...], [...]], [...], [...]], [...]]]), ('b', [1, [0, [...], [...], [2, [...], [...], [...], [3, [...], [...], [...], [...]]], [3, [...], [...], [2, [...], [...], [...], [...]], [...]]], [...], [2, [0, [...], [...], [...], [3, [...], [...], [...], [...]]], [...], [...], [3, [0, [...], [...], [...], [...]], [...], [...], [...]]], [3, [0, [...], [...], [2, [...], [...], [...], [...]], [...]], [...], [2, [0, [...], [...], [...], [...]], [...], [...], [...]], [...]]]), ('c', [2, [0, [...], [1, [...], [...], [...], [3, [...], [...], [...], [...]]], [...], [3, [...], [1, [...], [...], [...], [...]], [...], [...]]], [1, [0, [...], [...], [...], [3, [...], [...], [...], [...]]], [...], [...], [3, [0, [...], [...], [...], [...]], [...], [...], [...]]], [...], [3, [0, [...], [1, [...], [...], [...], [...]], [...], [...]], [1, [0, [...], [...], [...], [...]], [...], [...], [...]], [...], [...]]]), ('a', [3, [0, [...], [1, [...], [...], [2, [...], [...], [...], [...]], [...]], [2, [...], [1, [...], [...], [...], [...]], [...], [...]], [...]], [1, [0, [...], [...], [2, [...], [...], [...], [...]], [...]], [...], [2, [0, [...], [...], [...], [...]], [...], [...], [...]], [...]], [2, [0, [...], [1, [...], [...], [...], [...]], [...], [...]], [1, [0, [...], [...], [...], [...]], [...], [...], [...]], [...], [...]], [...]])]
Sorry for the extra-long line, but I figured it would be more consistent with the whole error...
If I'm not clear enough, please don't hesitate to tell me and I'll give more details.
Thanks for your time and explanations :-)
-
-
manoj prashant k over 6 yearsYes, using dictionaries is the best way to solve this .
-
cs95 over 6 yearsOrder suffers here. Actually, a defaultdict is overkill in the face of
setdefault
. -
cs95 over 6 yearsHmm, not explicitly, but the use of lists and tuples would indicate otherwise... anyway, that's on OP.
-
cs95 over 6 yearsYou are going to lose data if the lists have more than one element. I recommend
extend
instead -
Etsaf over 6 yearsseems nice but for some reason it doesn't work for me : python raises the following error after the line dd[k].extend(v[0]) >>>>>: Traceback (most recent call last): File "<stdin>", line 3, in <module> TypeError: 'int' object is not iterable
-
Alexander over 6 years@EtienneS It should be
dd[k].extend(v)
instead ofdd[k].extend(v[0])
. Note thatdd[k].append(v[0])
would work if there is only one number in the list for each tuple pair. -
Greenonline about 2 yearsThis seems like a joke answer... in the first point your answer is to google for the solution, and in the second point you just re-iterate what the error message says.
-
xNoobmaster69x about 2 yearsThere is already a thread about this error also in unix stackexchange and it is common for the error message to contain the solution.
-
Greenonline about 2 yearsJust to clarify, SE is a Q&A site, not a forum of threaded messages, so there may be a question (but not a thread) relating to this error already on SE.Unix. If so, and you know what that link is, then why not include a link to that question, in order to save the OP from having to search for it themselves (however, such a link would have probably served better as a comment). WRT to the second point, it would have served better as a comment, under the OP's question, asking them whether they have already performed the suggestions from the error message.