How to make an index combining values of lists nested in tuples?

72

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])]
Share:
72

Related videos on Youtube

Etsaf
Author by

Etsaf

Updated on December 03, 2022

Comments

  • Etsaf
    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
    manoj prashant k over 6 years
    Yes, using dictionaries is the best way to solve this .
  • cs95
    cs95 over 6 years
    Order suffers here. Actually, a defaultdict is overkill in the face of setdefault.
  • cs95
    cs95 over 6 years
    Hmm, not explicitly, but the use of lists and tuples would indicate otherwise... anyway, that's on OP.
  • cs95
    cs95 over 6 years
    You are going to lose data if the lists have more than one element. I recommend extend instead
  • Etsaf
    Etsaf over 6 years
    seems 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
    Alexander over 6 years
    @EtienneS It should be dd[k].extend(v) instead of dd[k].extend(v[0]). Note that dd[k].append(v[0]) would work if there is only one number in the list for each tuple pair.
  • Greenonline
    Greenonline about 2 years
    This 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
    xNoobmaster69x about 2 years
    There is already a thread about this error also in unix stackexchange and it is common for the error message to contain the solution.
  • Greenonline
    Greenonline about 2 years
    Just 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.