Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python

Nancy Melucci
seal-mask
.a{fill-rule:evenodd;}techdegree
Nancy Melucci
Front End Web Development Techdegree Student 34,491 Points

Zip a list of lists and a second list as keys and values.

I have a Python assignment to 1) Create a list of list composed of random numbers 2) Create a list of values based on the random numbers. Specifically, determine whether the number is even or odd and then append it to a new list. 3) Create a dictionary out of these two lists. The number is the key and odd/even string is the value. Of course, the number cannot appear more than once.

I have accomplished the easy stuff...1 and 2. I assume I need to flatten the list of lists. I cannot accomplish the zipping of the two lists. I presume that it might be straightforward to filter out the repeated digits but I can't even start to think about that until I do the main task.

I did the collections tutorial a while ago but I can't figure out (on reviewing) where the hints to do this might be. If I am missing that by all means, point that out.

Thanks. Any help is appreciated. What I have so far is shown. Don't laugh. ; )

def makealist(row, column):
    list = [[random.randint(0, 100) for x in range(row)] for y in range(column)]

    return list


def printlist(list):
    for item in list:
        print(item[0], ', '.join(map(str, item[1:])))

    return list


def labelValues(list):
    numDict = {}
    values = []
    oddEven = " ";
    keys = lambda list: [item for sublist in list for item in sublist]
    for key in keys:
        if key % 2 == 0:
            oddEven = "Even"
            values.append(oddEven)
        else:
            oddEven = "Odd"
            values.append(oddEven)


    print(values)
    numDict = dict(zip(keys, values))
    print(numDict)
    return values


list = makealist(10, 10)
labelValues(list)

2 Answers

Jon Baum
Jon Baum
13,863 Points

There are several points I would like to address concerning the code and the situation.

Firstly lets just get a mild syntatic issue out of the way. The use of list as a variable is dubious. There is a built-in function by the name of list that is responsible for transforming other collections into lists.

print list((1, 2, 3))
> [1, 2, 3]

Due to the fact that list is a built in function, we would want to avoid naming variables list. The code you have written won't cause any collisions via shadowing. In this case the issue doesn't manifest but if you had defined list as a function instead and tried to invoke it, it could cause issues. To that effect, I recommend renaming your list variable lst just to avoid confusion.

def makealist(row, column):
    lst = [[random.randint(0, 100) for x in range(row)] for y in range(column)]
    return lst

Secondly lets discuss what we need to accomplish for part 2 and 3:

  1. Create a list of values based on the random numbers. Specifically, determine whether the number is even or odd and then append it to a new list.
  2. Create a dictionary out of these two lists. The number is the key and odd/even string is the value. Of course, the number cannot appear more than once.

We can accomplish this task in a simple two step process. The first thing to do is recognize that we shouldn't be concerned with zipping lists of lists. This creates undo complications. A mantra I've come to live by in my coding is Keep your datastructures as simple as possible until otherwise necessary. Considering the logical flow of operations suggested we want to transform your data first

def even_odd:
  return [(x, 'even' if x % 2 == 0 else 'odd') for x in lst]
test = [1,2,3,4]
print even_odd(test)
> ['odd', 'even', 'odd', 'even']

Then filter the resultant data. However, then we have to deal with lists nested in lists and tuples. It is simpler flatten our data into a single list without duplicates then perform the transformation.

To flatten the list and remove duplicates we have an excellent built-in collection called a set. Now, I'm not sure if everyone who may read this knows how sets work so I'll include a brief explaination here. Sets are essentially lists of elements that CANNOT include duplicates.

list(1,2,3)
> [1, 2, 3]
list (1,2,3,3)
> [1, 2, 3, 3]
set([1,2,3])
> set([1, 2, 3])
set([1,2,3,3])
> set([1, 2, 3])

By using a set, we totally remove the opportunity for duplicates. Sets are a mathematical construct so they have other properties in addition to the non-duplication factor that can be used in other circumstances. However the python documentation and its deprecated version provide documentation on the possible functionality that is included in python. Now we can use sets to remove duplicates while flattening the list:

def flatten_and_deduplicate(lst):
  set_of_vals = set()
  for sublist in lst:
    for item in sublist:
      set_of_vals.add(item)
    return [x for x in set_of_vals] #Converting the set to a list

test = [[1,2,3],[1,2],[1,2,3,4]]
print test
> [[1, 2, 3], [1, 2], [1, 2, 3, 4]] 
print flatten_and_deduplicate(test)
> [1, 2, 3, 4]

Next we'll take advantadge of a technique not heavily discussed in the Treehouse courses which is dictionary comprehensions. Dictionary comprehensions are basically the same as list comprehensions except they allow us to build dictionaries in the same way we build list comprehensions. For some examples:

# Creating a list w/ key, value structure
test = [('name', 'Jim'), ('occupation', 'wizard of wizardry'), ('pet', 'lopsided goldfish')]
{ key : value for (key, value) in test}
> {'name': 'Jim', 'occupation': 'wizard of wizardry', 'pet': 'lopsided goldfish'}
# Manipulating elements into more complicated forms
test = [1, 2, 3, 4]
{ key : key * 2 for key in test}
> {1: 2, 2: 4, 3: 6, 4: 8}

We can then use this approach in combination with the guts of our even_odd function from earlier in ordet to develop a dictionary comprehension that uses the number as the key and provides the evenness/oddness as the value.

def dictionary_of_evenodd(lst):
  return { key: 'even' if x % 2 == 0 else 'odd' for x in lst}
test = [1,2,3,4]
print dictionary_of_evenodd(test)
> {1: 'odd', 2: 'even', 3: 'odd', 4: 'even'}

Since we reduced the list of lists earlier into a single list, we don't have to worry about the complicated implementation details of the lists of lists. Furthermore, we don't have to worry about tuples or duplicates. As they say: simplify THEN calculate. Combining our techniques into a singular function we wind up with the following:

def labelValues(lst):
  set_of_vals = set()
  for sublist in lst:
    for listitem in sublist:
      set_of_vals.add(listitem)
  out_dict = {key: "even" if key % 2 == 0 else "odd" for key in set_of_vals}
  return out_dict

Now that's not to say in terms of code-golf this is the most 'optimized' nor pythonic way of handling this. However, it effectively handles our convoluted lists of lists pretty well. Combining everything into a final form we have.

import random
def makealist(row, column):
    lst = [[random.randint(0, 100) for x in range(row)] for y in range(column)]
    return lst


def printlist(lst):
    for item in lst:
        print(item[0], ', '.join(map(str, item[1:])))
        return lst


def labelValues(lst):
  set_of_vals = set()
  for sublist in lst:
    for listitem in sublist:
      set_of_vals.add(listitem)
  out_dict = {key: "even" if key % 2 == 0 else "odd" for key in set_of_vals}
  return out_dict

list = makealist(10, 10)
print labelValues(list)
#Example output
> {2: 'even', 3: 'odd', 4: 'even', 5: 'odd', 6: 'even', 7: 'odd', 9: 'odd', 10: 'even', 
13: 'odd', 14:'even', 15: 'odd', 16: 'even', 17: 'odd', 20: 'even', 21: 'odd', 25: 'odd', 
26: 'even', 27: 'odd', 28:'even', 30: 'even', 31: 'odd', 32: 'even', 33: 'odd', 34: 'even',
35: 'odd', 36: 'even', 38: 'even', 39: 'odd', 40: 'even', 42: 'even', 47: 'odd', 48: 'even',
49: 'odd', 50: 'even', 51: 'odd', 52: 'even', 54: 'even', 55: 'odd', 56: 'even', 60: 'even',
61: 'odd', 62: 'even', 63: 'odd', 64: 'even', 66: 'even', 69: 'odd', 72: 'even', 73: 'odd',
74: 'even', 75: 'odd', 77: 'odd', 82: 'even', 83: 'odd', 84: 'even', 87: 'odd', 89: 'odd', 
91: 'odd', 92: 'even', 93: 'odd', 94: 'even', 95: 'odd', 97: 'odd'}

Hope this helps! Please let me know if there are any typos/corrections/clarifications needed. Cheers!

Nancy Melucci
seal-mask
.a{fill-rule:evenodd;}techdegree
Nancy Melucci
Front End Web Development Techdegree Student 34,491 Points

Wow. That so much more patient and excellent help than I was expecting. I just woke up so I will go through it again carefully later today. I suspect it will help me fix my problem and learn from this exercise.

Have a great weekend. NJM

Jon Baum
Jon Baum
13,863 Points

My pleasure and I hope it does!