1

I am trying to create a dictionary of colors where an integer maps to a color. In my first list l1, it has 177 items but only 5 unique integers (0 to 4). In the second list, it has 5 html colors. I am trying to create a dictionary where each color will map to a unique integer.

 l1=[3 2 3 3 0 2 4 4 2 3 2 2 4 0 3 2 2 2 1 3 2 3 2 2 2 0 3 1 0 2 2 2 4 2 4 2 0
     2 0 4 0 4 2 0 2 2 2 4 1 3 2 2 2 1 0 3 3 2 0 2 3 4 1 0 0 1 3 1 3 1 4 3 4 1
     4 0 2 3 2 0 4 1 3 0 0 4 0 4 0 2 2 1 2 2 1 0 4 4 3 1 3 2 2 2 4 4 2 0 3 4 4
     0 3 4 3 4 2 2 2 3 3 1 0 2 3 1 1 4 0 1 2 0 0 2 0 0 0 0 2 3 1 0 3 3 3 2 2 3
     3 0 0 0 2 0 3 2 0 0 0 2 2 0 4 3 3 0 2 2 3 2 3 3 0 2 0 4 3]

 l2=['#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF']

Here is my code:

    color_map=dict(zip(l1,l2))
    print color_map

However, I get an incocomplete dictionary:

{0: '#0000FF', 2: '#FFFFFF', 3: '#00FF00'}

How do i fix this?

jxn
  • 7,685
  • 28
  • 90
  • 172
  • 2
    in order to use `zip` and get a perfect match, you need two lists/sets of the same length. – levi Jan 31 '15 at 00:26

5 Answers5

1

You need a set so you get all unique numbers from l:

print(dict(zip(set(l)),l2))
{0: '#000000', 1: '#FFFFFF', 2: '#FF0000', 3: '#00FF00', 4: '#0000FF'}

If you always want the numbers sorted:

 print(dict(zip(sorted(set(l)),l2)))

You will always need to have only 5 unique values in l if you only have five values in l2 or again you will lose data.

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
1

Based on the code you've presented, I would suggest considering an enum.Enum or enum.IntEnum object instead of a dictionary (docs). It's hard to say for sure, but IntEnum may work better for you here.

You can create your IntEnum this way:

l2=['#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF']
from enum import IntEnum
Color = IntEnum('Color', ' '.join(l2))

Now all of your colors have been automatically mapped to an integer value (beginning with 1; the reason for starting with 1 instead of zero is so that all members of an Enum evaluate to True).

You can iterate over Color and access member names and member values, similar to how you would with a dictionary:

for color in Color:
    print(color.name, color.value)

Notice that when you access the member by key like in a dictionary, the IntEnum member object itself is returned, not the integer it's mapped to:

print(Color['#000000'])

...however, this probably won't matter to you, because since it's an IntEnum the member objects act like integers, including for the purposes of comparison, etc:

for color in Color:
    if color == 1:
        print(color.name, ' is 1!')

print(Color['#000000'] == 1) # will print either True or False 
c = Color(1)
print(c) # will print the Color member c, which is mapped to 1 

The above is the key reason I am thinking this may be a better alternative. Your l1 list is full of integers that represent colors. The ideal thing would be to fill it with Color members instead of integers:

for index, number in enumerate(l1):
    l1[index] = Color(number)

However, if you can't/don't want to do that, you can still compare the integers to the Color members (I assume you don't have any interest in "adding", "multiplying", etc, colors together).

So, you could maybe do things like this:

print(any(number == Color['#000000'] for number in l1))

The Color enum also comes with a built-in dictionary object (Color.__members__) that will return a dictionary with the member names as the keys and the member itself as the value.

Community
  • 1
  • 1
Rick
  • 43,029
  • 15
  • 76
  • 119
0

If the unique integers are consecutive, you can use enumerate():

>>> dict(enumerate(l2))
{0: '#000000', 1: '#FFFFFF', 2: '#FF0000', 3: '#00FF00', 4: '#0000FF'}
Simeon Visser
  • 118,920
  • 18
  • 185
  • 180
0

You may try to use set() to get all the unique integer of l1:

l1_list=list(set([3,2,3,3,0,2,4,4,2,3,2,2,4,0,3,2,2,2,1,3,2,3,2,2,2,0,3,1,0,2,2,2,4,2,4,2,0,2,0,4,0,4,2,0,2,2,2,4,1,3,2,2,2,1,0,3,3,2,0,2,3,4,1,0,0,1,3,1,3,1,4,3,4,1,4,0,2,3,2,0,4,1,3,0,0,4,0,4,0,2,2,1,2,2,1,0,4,4,3,1,3,2,2,2,4,4,2,0,3,4,4,0,3,4,3,4,2,2,2,3,3,1,0,2,3,1,1,4,0,1,2,0,0,2,0,0,0,0,2,3,1,0,3,3,3,2,2,3,3,0,0,0,2,0,3,2,0,0,0,2,2,0,4,3,3,0,2,2,3,2,3,3,0,2,0,4,3]))
l2=['#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF']

color_map=dict(zip(l1_list,l2))
print color_map

Output:

{0: '#000000', 1: '#FFFFFF', 2: '#FF0000', 3: '#00FF00', 4: '#0000FF'}
lqhcpsgbl
  • 3,694
  • 3
  • 21
  • 30
-1

@Simeon Visser's answer is the most concise one for the specific example you provided (using integers from 0 to 4). But, if what you wanted is to have a sequence of #s like {0: '#0000FF', 2: '#FFFFFF', 3: '#00FF00'} where all the items show up from the original list (even repeated), this won't work.

It seems your intention, however, was to actually grab the colors for all the corresponding items of the list. If that's the case, what you can do is use Simeon's answer and combine it with your original list like in the following way:

colorDict = dict(enumerate(l2))
colors = [colorDict[colorIndex] for colorIndex in l1]

This will map all the colors to a new list based on the integer sequence from l1. Hope that helps.

Eithos
  • 2,421
  • 13
  • 13