Search code examples
pythonpython-2.7collectionsanagramdefaultdict

defaultdict(list) concatenating all the values into one list


What I am trying to do:

Write a method to sort an array of strings so that all the anagrms are next to each other.

I have the following code:

from collections import defaultdict
res = defaultdict(list)
L = ['foo', 'poo', 'k', 'fo', 'ofo', 'oof']

for w in L:
    res["".join(sorted(w))].append(w)

But now I want to take all the values in res and combine them into one list.

I tried this:

output =[]
for items in res.values():
    output.append(i for i in items)

But that gave me:

>>> output
[<generator object <genexpr> at 0x102a4d1e0>, <generator object <genexpr> at 0x102a95870>, <generator object <genexpr> at 0x102a958c0>, <generator object <genexpr> at 0x102a95910>]

How can I display the items in one list properly?

Desired:

['foo','ofo', 'oof','poo', 'k', 'fo',]

(all the anagrams are together, order doesn't matter as long as they are adjacent in the list.)


Solution

  • When you do -

    output.append(i for i in items)
    

    You are actually appending the generator expression - i for i in items - into output list, as you can also see from the repr result of your output list. This does not automatically evaluate the generator expression and add the results. What you should have done was to use output.extend(). Example -

    >>> output = []
    >>> for items in res.values():
    ...     output.extend(items)
    ...
    >>> output
    ['fo', 'k', 'foo', 'ofo', 'oof', 'poo']
    

    This would evaluate the expression and append each element from the iterable (generator expression) to the list as a separate element.


    But If you want to convert a single list from all the list values of res dictionary, An much easier way would be to use itertools.chain.from_iterable. Example -

    >>> from itertools import chain
    >>> output = list(chain.from_iterable(res.values()))
    >>> output
    ['fo', 'k', 'foo', 'ofo', 'oof', 'poo']