Zipped Dict - random numbers?

Hello friends,

I’m working through the off-platform medical insurance costs project.

I have two lists that i’ve zipped into a dictionary with the following code:

objective_two = dict(zip(num_of_children_int, per_charges_int))

I want to use this to plot a graph. However, when I print them, the dictionary has random numbers?

num_children_int: [0, 1, 3, 0, 0, 0, 1, 3, 2, …]
per_charges_int: [16884, 1725, 4449, 21984, 3866, 3756, 8240, …]
objective_two: {0: 29141, 1: 9377, 3: 10600, 2: 12629, 5: 14478, 4: 19496}

I was expecting:

objective_two: {0:16884, 1:1725, 3:4449, 0:21984, …}

Is this the correct format i’ll need? Where am I going wrong please?

Thank you

The problem is that your num_children_int list contains the same value (for example zero) multiple times

you intent to use these values as keys for the dictionary, but using an key that is already in the dictionary will overwrite the value for the key

some code I used to test:

num_children_int = [0, 1, 3, 0, 0, 0, 1, 3, 2]
per_charges_int = [16884, 1725, 4449, 21984, 3866, 3756, 8240]
for child, charge in zip(num_children_int, per_charges_int):
    print(child, charge)

You’ve a couple of issues going on here.
Firstly, dictionaries have unique keys. So, everytime it gets to the same value in num_children_int it’ll jusyt overwrite it instead of creating a new entry.
Secondly, dictionaries are unordered. So, you wont get {0: hjfh, 1: fihfi, 2: dfdhiuf…} by default.

If you’ve got a link to the lesson we can have a look at what they’re trying to get you to do.

1 Like

Ah fantastic, thank you both for explaining this!

I want to plot these key:values on a chart - but I will play around with it now I realised where I went wrong.

Thank you for the quick response.


Consider how much space your raw data takes up. Do we want that data duplicated in another data structure? Not really. Easier just to poll the raw data when we need it. That’s where iterators come in. They don’t take up any space in memory (or more than a smidgen). Regardless the size of the data, the interator is always the same size. We tell it where the data is, and it implements its next() method to traverse the data from start to end (StopIteration).

In other words, when you create a zip object, don’t cast it to a list or other structure. Just consume it, as intended. @stetim94’s code above is good example.

1 Like

Ah interesting. I definitely need to get better with this.

Thanks mtf!

1 Like

Even in the case of non-consumables, we can still use them in a transient form that will evaporate, anyway. Think along these lines so that iterators and generators make sense, else they won’t.

Consider this example taken from a Python 3 lesson:

import string
lower_list = list(string.ascii_lowercase)
upper_list = list(string.ascii_uppercase)
number_list = list(range(0, 10))
count = 0

Notice each object is a list cast from a native or class object. But why would we ever do that? This just sucked up a whole bunch of memory that may not ever be recovered unless we unhook those variables.

for x in lower_list:
  for y in upper_list:
    for z in number_list:       
      count +=1
print (count)


for x in string.ascii_lowercase:
  for y in string.ascii_uppercase:
    for z in range(0, 10):       
      count +=1
print (count)

Which form leaves the smallest memory footprint?

As a side note, for iterative purposes a range object should never be cast to a list. It’s just not necessary and doing so consumes resources needlessly. If we want to assign it to a variable we can map it, which makes it consumable; again, we leave little or no foot print.

Here is an example of a consumed iterator (a map object fashioned from a range object)…

def reverse(s):
        a = [*s]
        b = map(lambda x: x, range(len(a)))
        while True:
            a.insert(next(b), a.pop())
    except StopIteration:
        return ''.join(a)

>>> reverse('atmosphere')

except StopIteration:

The object b has been consumed.

>>> [*b]