1

I have some data I have zipped together using itertools.zip_longest

import itertools
names = 'Tim Bob Julian Carmen Sofia Mike Kim Andre'.split()
locations = 'DE ES AUS NL BR US'.split()
confirmed = [False, True, True, False, True]
zipped_up = list(itertools.zip_longest(names, locations, confirmed))

if I print zipped_up the way it is now I get the following:

[('Tim', 'DE', False), ('Bob', 'ES', True), 
('Julian','AUS', True), ('Carmen', 'NL', False), 
('Sofia', 'BR',True), ('Mike', 'US', None), 
('Kim',None, None),('Andre', None, None)]

This is fine, the missing values are given "None" as a default. Now I want to change the "None" values to '-'.

It seems like I should be able to do so in the following nested loops. If I include a print statement in the code below, it appears everything works the way I wanted:

for items in zipped_up:
    for thing in items:
        if thing == None:
            thing = '-'
        print(thing)

But if I print zipped_up again (outside the loops), the 'None' values have not changed. Why Not? Is it something to do with the data type of the list items, which are tuples?

I have referenced some other stackoverflow threads including this one but have been unable to use it: finding and replacing elements in a list (python)

Erich Purpur
  • 1,337
  • 3
  • 14
  • 34
  • 2
    "Why Not? Is it something to do with the data type of the list items, which are tuples?" No, not at all. `thing = '-'` simply assigns the value `'-'` to the local variable `thing`, and you shouldn't expect it to affect the list you are iterating over. There's definitely a duplicate somewhere, but I suggest your read https://nedbatchelder.com/text/names.html – juanpa.arrivillaga Sep 19 '18 at 22:40
  • Can you just post the original before you zipped and your goal and maybe there is a better way – vash_the_stampede Sep 19 '18 at 22:51
  • The best way to do this is to use `fillvalue`. But you can do the conversion by rebuilding the output, eg `[[thing or '-' for thing in items] for items in zipped_up]`, or `[tuple(thing or '-' for thing in items) for items in zipped_up]` if you need the inner sequences to be tuples. – PM 2Ring Sep 19 '18 at 22:55
  • @PM2Ring aren't we only using `zip_longest` over `zip` to utilize `fillvalue` to begin with? – vash_the_stampede Sep 19 '18 at 23:04
  • @vash_the_stampede names, locations, and confirmed are the original data – Erich Purpur Sep 19 '18 at 23:39
  • 1
    @vash_the_stampede Kind of. It's main purpose is so the zipped-up list doesn't finish when the shortest source iterable is finished, but to do that we need some kind of fill value. – PM 2Ring Sep 19 '18 at 23:40
  • @PM2Ring that's what I'm saying, the whole purpose of `zip_longest(*iterables, fillvalue=None)` is for when we have uneven and need to use a fill, if not we would have used zip, correct? – vash_the_stampede Sep 19 '18 at 23:42

2 Answers2

5

Simply use the fillvalue argument:

zipped_up = list(itertools.zip_longest(names, locations, confirmed, fillvalue='-'))

>>> zipped_up
[('Tim', 'DE', False), ('Bob', 'ES', True), ('Julian', 'AUS', True), ('Carmen', 'NL', False), ('Sofia', 'BR', True), ('Mike', 'US', '-'), ('Kim', '-', '-'), ('Andre', '-', '-')]
sacuL
  • 49,704
  • 8
  • 81
  • 106
3

First, you are trying to change elements in tuples, but tuples are immutable objects.
The only way to "change" them is to create new ones on the basis of existing ones.

Second, this part of your code

for thing in items:
    if thing == None:
        thing = '-'

replaces only the content of the variable thing, so even if you would have mutable objects in your zipped_up list - such as (nested) lists - your code would not change them anyway.

So, if your for whatever reason don't want to accept the solution of sacul and instead edit your loop in loop approach, you may append newly created tuples to the new, empty list.

As in this (not very nice) code:

result = []
for a, b, c in zipped_up:
    a = '-' if a is None else a
    b = '-' if b is None else b
    c = '-' if c is None else c
    result.append((a, b, c))

print(result)

Output:

[('Tim', 'DE', False), ('Bob', 'ES', True), ('Julian', 'AUS', True), ('Carmen', 'NL', False), ('Sofia', 'BR', True), ('Mike', 'US', '-'), ('Kim', '-', '-'), ('Andre', '-', '-')]

MarianD
  • 13,096
  • 12
  • 42
  • 54