Alex
Alex

Reputation: 13

Iterating over a dictionary of list elements

I'm very new to Python (2.x) and trying to understand how to iterate over a dictionary containing multiple lists:

dict = {'list_1':[3, 'green', 'yellow', 'black'], 'list_2':[2, 'green', 'blue']}

I am trying to create a new list containing all of the unique values of these lists, but ignoring the first item (the integer). The result I'm looking for would be:

['green', 'yellow', 'black', 'blue']

Here is one of my many attempts. I'm quite lost, so if somebody could explain I would be most grateful.

newlist = []
for colors in dict.values() [1:]:
    if not colors in newlist:
        newlist.append(colors)

Upvotes: 1

Views: 392

Answers (7)

Chris Seymour
Chris Seymour

Reputation: 85775

One way using itertools.chain to flatten the dict values into a single list then list comprehension to filter out the non-string values and finally set for the unique values:

In [1]: from itertools import chain
In [2]: dict={'list_1':[3,'green','yellow','black'],'list_2':[2,'green','blue']}
In [3]: set([x for x in chain(*dict.values()) if isinstance(x, str)])
Out[3]: set(['blue', 'black', 'green', 'yellow'])

If really want to remove the first item in the list only and not all ints then similarly you could do:

In [4]: set(chain(*[x[1:] for x in dict.itervalues()]))
Out[4]: set(['blue', 'black', 'green', 'yellow'])

The first answers fails if you want all ints not in the first position in the final set and second fails for none ints found at the first position so you should state what should happen for these cases.

Upvotes: 1

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250891

Use set.union:

>>> dic = {'list_1':[3, 'green', 'yellow', 'black'], 'list_2':[2, 'green', 'blue']}
>>> set().union(*(x[1:] for x in dic.itervalues()))
set(['blue', 'black', 'green', 'yellow'])

If a list is required simply pass this set to list().

The working version of your attempt, though it is not efficient;

newlist = []
for colors in dic.values():
    lis = colors[1:]        #do slicing here
    for item in lis:
        if item not in newlist:
            newlist.append(item)
print newlist #['green', 'blue', 'yellow', 'black']

Upvotes: 1

roman
roman

Reputation: 117345

here's one-liner for you

>>> d = {'list_1':[3, 'green', 'yellow', 'black'], 'list_2':[2, 'green', 'blue']}
>>> list(set(i for x in d.itervalues() for i in x[1:]))
['blue', 'black', 'green', 'yellow']

As Haidro says, don't name a dictionary dict

Upvotes: 0

Nick Burns
Nick Burns

Reputation: 983

theColours = set()
for colours in d.values():
    [theColours.add(colour) for colour in colours[1:]]
list(theColours)

Upvotes: 0

TerryA
TerryA

Reputation: 59974

If you print dict.values(), you get:

[[2, 'green', 'blue'], [3, 'green', 'yellow', 'black']]

Hence, when you're trying to slice it, you get:

[[3, 'green', 'yellow', 'black']]

Thus, you want to slice colors instead of the dict.values():

for colors in t.values():
    colors = colors[1:]

Now there's another problem. You're checking if the list has been seen in the list, instead of each item. So you have to loop again.

for colors in t.values():
    colors = colors[1:]
    for color in colors:

Note that this can lead your script to not have such great performance, so you could probably do something like:

>>> from itertools import chain
>>> [i[1:] for i in t.values()]
[['green', 'blue'], ['green', 'yellow', 'black']]
>>> list(chain.from_iterable(i[1:] for i in t.values()))
['green', 'blue', 'green', 'yellow', 'black']

Therefore, integrated into your code:

new = set() # Better for performance to use sets
for color in chain.from_iterable(i[1:] for i in t.values()):
    if color not in new:
        new.add(color)

print new

Prints:

set(['blue', 'black', 'green', 'yellow']) # If you need order, use a list instead.

By the way, don't name a dictionary dict. It overrides the built-in type.

Upvotes: 0

Rohit Jain
Rohit Jain

Reputation: 213223

This would work, even if you have integer at some other index:

>>> di = {'list_1':[3, 'green', 'yellow', 'black'], 'list_2':[2, 'green', 'blue']}
>>> set(x for value in di.values() for x in value if not isinstance(x, int))
set(['blue', 'black', 'green', 'yellow'])

Upvotes: 0

Craig
Craig

Reputation: 4399

Create a set to remove duplicates and then run it through the sorted() built-in to return a list.

newlist = sorted(set(dict.values()[1:]))

Upvotes: -1

Related Questions