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)

7
  • 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 nedbatchelder.com/text/names.html Commented Sep 19, 2018 at 22:40
  • Can you just post the original before you zipped and your goal and maybe there is a better way Commented Sep 19, 2018 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. Commented Sep 19, 2018 at 22:55
  • @PM2Ring aren't we only using zip_longest over zip to utilize fillvalue to begin with? Commented Sep 19, 2018 at 23:04
  • 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. Commented Sep 19, 2018 at 23:40

2 Answers 2

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', '-', '-')]
Sign up to request clarification or add additional context in comments.

3 Comments

The important aspect of this question is probably explaining why the OP's attempt didn't work
@juanpa.arrivillaga but can we say, why else would he use zip_longest over zip if not to use fillvalue?
Sure, and I would definitely point that out, but you are simply leaving them with a fundamental misunderstanding of the semantics of the language, and simply giving them an alternative solution.
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', '-', '-')]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.