NyaSol
NyaSol

Reputation: 567

Understand Zip and list comprehension in python

I have a function "to_underscore" that takes a CamelCase string and convert it to snake_case

def to_underscore(string):
    index_counter = []

    if isinstance(string, int):
        return str(string)

    for i in range(len(string)):
        if string[i].isupper():
            index_counter.append(i)

    new_string = [string[i:j] for i,j in zip (index_counter,index_counter[1:] + [None])]
    string = '_'.join(new_string)

    return ''.join(c.lower() for c in string)

I didn't quite understand how the folowing line is executed:

string = "ThisIsCamelCase"
index_counter = [0,4,6,11]

// this line - >
for i,j in zip (index_counter,index_counter[1:] + [None]):
        print(i,j)

// output -> (0,4),(4,6),(6,11),(11,None)

what does index_counter[1:] +[None] means ? and why this is the output?

I understand zip and what we are trying to do, but the output is not clear.

if you can walk through the execution this will be optimal.

Upvotes: 1

Views: 1129

Answers (4)

Neil
Neil

Reputation: 3291

Just for future reference, print is your friend. Try this:

print(index_counter)
print(index_counter[1:])
print(index_couter[1:] + [None])
# When printing a zip object (or any iterable), just cast to a list first so you can see what's in it
print(list(zip(index_counter, index_counter[1:] + [None])))

Chances are if you look at the output you're going to know what's going on.

Upvotes: 0

deceze
deceze

Reputation: 522085

index_counter = [0, 4, 6, 11]

Now, index_counter[1:] is:

[4, 6, 11]

index_counter[1:] + [None] is:

[4, 6, 11, None]

zip this with index_counter, and you're iterating over these pairs:

0   4   6   11
4   6   11  None

The None needs to be added, as zip would otherwise stop at the (6, 11) pair. Instead you could also use itertools.zip_longest.

Upvotes: 3

legoscia
legoscia

Reputation: 41548

index_counter[1:] returns a sublist starting from element 1 (that is, the second element, since indexes start at 0). In this case, that would be [4,6,11].

Then we add a None element at the end, so that the two lists have the same length and we can call zip on them.

zip([0,4,6,11], [4,6,11,None]) returns a number of pairs, picking one element from both lists at a time:

[(0,4),     # first element from both lists
 (4,6),     # second element from both lists
 (6,11),    # third element from both lists
 (11,None)] # fourth element from both lists

These pairs can then be used to pick out a portion of the string, from one capital letter to the next.

Upvotes: -1

kutschkem
kutschkem

Reputation: 8163

index_counter[1:] +[None]

This is a list concatenation, index_counter is concatenated with a list containing a None value. The part [1:]means the sublist from index 1 to the end. So the whole expression creates a list where the first element is removed, and a Noneis added at the end.

zip creates a list of pairs of the entries in the two lists with the same indices.

The end result is that there are pairs of (index, next index).

Upvotes: 0

Related Questions