Can you help me understand how the zip function is working in this code?
I am currently learning python more in depth with a Udemy course (Python deep dive with Fred Baptiste). I am trying to solve Kata on codewar (currently kyu5 ) . Firt kata post confinement (I was very busy during this time so I had to stop learning python) I tried this one . https://www.codewars.com/kata/5946a0a64a2c5b596500019a Relatively easy to solve. But look at the best practice solution I found this one : def split_and_add(numbers, n): for _ in range(n): middle = len(numbers) // 2 left = numbers[:middle] right = numbers[middle:] numbers = [a + b for a, b in zip((len(right) - len(left)) *  + left, right)] if len(numbers) == 1: return numbers return numbers Could someone explain to me how this line work ? numbers = [a + b for a, b in zip((len(right) - len(left)) *  + left, right)]
5/21/2020 6:30:42 AMnicolas seespan
12 AnswersNew Answer
In reality it should never need more than 1 zero padded on the left. The length of the original pre-split list is either even leaving both the same length already or odd, needing one 0 padded on the left. It could just as easily be written; left if len(right) == len(left) else +left Or whatever variation thereof you choose.
Oma Falk I would write it with zip_longest but that need the two parts to be reversed, so that the extra zero is added to the actual beginning. Not sure if this is less confusing though :) https://code.sololearn.com/chP7hOZsDovs/?ref=app
(len(right)-len(left)) *  + left This part is passed as the first argument to the zip function. What it does is pads the left of the list "left" with the difference in length between the list "right" and "left" so that they will have the same length. The list "right" is passed as the second argument of the zip function. The zip function takes in 2 iterables and then takes an element from each matching index and outputs them in an iterable of tuples. https://docs.python.org/3.3/library/functions.html#zip The whole rvalue statement together utilizes list comprehension. https://docs.python.org/3/tutorial/datastructures.html https://realpython.com/list-comprehension-python/ In this case you can kinda think of it as an inline for loop. The statement is basically the same as; numbers =  for a, b in zip((len(right)-len(left)) *  + left, right): numbers += a + b Where a is the nth element from the padded left list, and b is the nth element from right.
step by step zip ([1,2,3],[3,4,5]) evaluates to [(1,3),(2,4),(3,5)]. if left and right part have same length you are almost done by adding elements of tuple.: 4,6,8 but having an odd number of elements and splitting them leadst ti two lists of different length. lets say 1, 2,3,4,5 leadst to [1, 2] and [3,4,5] where left is [1,2] and right is [3,4,5] . now the solution adds leading zeros left, as much as needed to make it as long as right. he calculates the difference of len for it, creates a list or and with that left becomes [0,1,2]. now zip can do its work.
HonFu , Tibor Santa ~ swim ~ Subham not sure if this is the best solution. challenge in short: split and sum until 1 number is left. 1,2,3,4,5,6,7,8,9 split 1,2,3,4..... right justified 5,6, 7,8,9 add 5,7,9,11,13 ....
If it's about best practice, maybe it could be optimized for clarity? If you add one more line... lenDifference = (len(right) - len(left)) ... probably the following comprehension would be easier to understand. numbers = [ a + b for a, b in zip( lenDifference* + left, right ) ]
Codewars is really awesome, even from the basic level katas you can learn so much because you can then check how other people have solved it... Some are really creative and sometimes "too clever" but occasionally you have those ah-ha moments discovering really pythonic and efficient ways to approach a problem.
nicolas seespan, the title of your question is too vague, btw. Like this, hardly no one may take a look (except moderators, lol) and you get only a few answers (that not necessarily help you). Why not edit your title and make it something immediately obvious, like: 'Can you help me interpret this complicated list comprehension?'
Ha, zip_longest, nice! :-) Didn't know that one. Maybe time for me to take a look into that treasure box itertools myself.
Thanks everyone :-) I understand now. numbers = [a + b for a, b in zip((len(right) - len(left)) *  + left, right)] That's the (len(right) - len(left)) *  part that was confusing me. Yes of course the difference between len(right) - len(left) is either 0 or 1. If 1, you add a zero at the beginning of the shortest list which will always be left given the way // work with interger by default (but you can change that, thanks Python Deep dive, chapter in the different type of number :-) ) My solution was way less elegant, but as the skill are function of the time spend training, I can only do hobbyist solution. Still solving those problem is more fun than video game . def split_and_add(numbers, n): counter = n if len(numbers) == 1: c = numbers if n == 0: c = numbers else : c = [5,5] while counter > 0 and len(c) > 1 : # If statment for the first loop if counter == n: b = numbers else: b = c counter -= 1 c =  x = int(len(b) / 2) b1 = b[0:x] b2 = b[x:] if len(b1) > len(b2): c.append(b1) b1 = b1[1:] if len(b2) > len(b1): c.append(b2) b2 = b2[1:] for i in range(len(b1)): c.append(b1[i] + b2[i]) return c
i like codewars too. found one or another trick there.
Your question plus discussion is good advertising for Codewars. I feel like giving the site a try myself. 🙂