1

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

3 Answers 3

1

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])]
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, using dictionaries is the best way to solve this .
1

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

4 Comments

Order suffers here. Actually, a defaultdict is overkill in the face of setdefault.
Hmm, not explicitly, but the use of lists and tuples would indicate otherwise... anyway, that's on OP.
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
@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.
0

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

1 Comment

You are going to lose data if the lists have more than one element. I recommend extend instead

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.