Reputation: 23
I know there's a way to have the python map function execute for multiple iterators in one command, but I keep getting syntax or valueErrors, or if it does compile it just overwrites previous iterations or gives the wrong answer. What am I doing wrong?
num = ["1","2","3"]
num2 =["4","5","6"]
num3 = ["7","8","9"]
j = list(map(lambda x, y, z: int(x) and int(y) and int(z), num, num2, num3))
print(j) #[7, 8, 9]
print(reduce(lambda x, y: x+y, j)) #24
The goal is to have all numbers across multiple lists mapped from string to integer into one big list, then summed using reduce()
j should come out to [1,2,3,4,5,6,7,8,9] all ints
the reduce should sum it to 45
update: this way doesnt work either
num = ["1","2","3"]
num2 =["4","5","6"]
num3 = ["7","8","9"]
j = list(map(lambda x, y, z: int(x+y+z), num, num2, num3))
print(j) #[147, 258, 369]
print(reduce(lambda x, y: x+y, j)) #774
Upvotes: 2
Views: 4022
Reputation: 83527
Since you want to iterate over the elements of each list as one long list, it is easiest to just concatenate them:
nums = map(int, num + num2 + num3)
Upvotes: 0
Reputation: 152647
Given your desired intermediate output I'd say that map
isn't the right tool to get a j
containing the integers 1-9.
That's because map
with multiple iterators goes through the iterators simultaneously:
It doesn't repeat, that's just because it's a gif file.
In the first iteration it will return "1", "4", "7"
(the first elements of each iterable) the next iteration will return "2", "5", "8"
and the last iteration "3", "6", "9"
.
On each of these returns it will apply the function, in your first example in the first iteration that's
int("1") and int("4") and int("7")
which evaluates to 7
because that's the last truthy value of the chained and
s:
>>> int("1") and int("4") and int("7")
7
That also explains why the result is 24
because the results of the other iterations are 8
and 9
:
>>> int("2") and int("5") and int("8")
8
>>> int("3") and int("6") and int("9")
9
>>> 7 + 8 + 9
24
In your second example you added the strings (which concatenates the strings) and then converted it to an integer:
>>> "1" + "4" + "7"
"147"
>>> int("147")
147
So, you need the addition from your second approach but apply the int
to each variable like you did in the first example:
j = list(map(lambda x, y, z: int(x)+int(y)+int(z), num, num2, num3))
But for that problem I would probably use a different approach, especially if you want the "desired" j
.
To get that you need to chain
the iterables:
import itertools
chained = itertools.chain(num, num2, num3)
Then convert all of them to integers:
chained_integers = map(int, chained)
This chained_integers
is the iterator-equivalent to the [1, 2, 3, 4, 5, 6, 7, 8, 9]
list you wanted as j
. You could also use chained_integers = list(map(int, chained))
and print the chained_integers
before proceeding if you want to double-check that.
And finally to reduce
it I would actually use the built-in sum
function:
reduced = sum(chained_integers) # or "reduce(lambda x, y: x+y, chained_integers)"
Or the one-line-version:
sum(map(int, itertools.chain(num, num2, num3)))
map
:Even simpler would be a comprehension (in this case I used a generator expression) instead of the map
:
reduced = sum(int(v) for v in itertools.chain(num, num2, num3))
That's pretty short and easy to understand but I would like to present another example of how to do it using your own generator function:
def chain_as_ints(*iterables):
for iterable in iterables:
for item in iterable:
yield int(item)
And you could use it like this:
sum(chain_as_ints(num, num2, num3))
In this case a generator function is not really necessary (and probably not advisable given the alternatives) I just wanted to mention it for completeness.
Upvotes: 5