Reputation: 13
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
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
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
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
Reputation: 983
theColours = set()
for colours in d.values():
[theColours.add(colour) for colour in colours[1:]]
list(theColours)
Upvotes: 0
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
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
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