MAUCA
MAUCA

Reputation: 59

nested for loops in python - can some one explain

I'm studying how to use for loops and so on and I'm trying to come up with a way to make a string of similar characters sort itself so that no characters are repeated

# string of characters
chars = 'abbbababa'
# my idea was to make it an enumerated string
charsnum = enumerate(chars)
# while doing that I discovered the following
chars = 'babbbaba'
for i in charsnum:
    for j in charsnum:
        for z in charsnum:
            for k in charsnum:
                print(i,j,z,k)
# each time I add a loop the string becomes shorter 
(0, 'b') (1, 'a') (2, 'b') (3, 'b')
(0, 'b') (1, 'a') (2, 'b') (4, 'b')
(0, 'b') (1, 'a') (2, 'b') (5, 'a')
(0, 'b') (1, 'a') (2, 'b') (6, 'b')
(0, 'b') (1, 'a') (2, 'b') (7, 'a')

I know that the first loop iterates through all the values in charsnum, but what are the second, third, and so on for loops iterating through? Also, what could be a good solution to making my string 'babbbaba' in to a string like 'bababababa' or 'ababababa' where no values repeat.

Upvotes: 0

Views: 698

Answers (3)

user8685353
user8685353

Reputation:

Your question and example are really confusing, I think this is what you are looking for.

A way easier way to do this is to use a list comprehension, which will iterate through your set of characters in a more compact, pythonic manner.

chars = 'abbbababa'
print( [i for i in chars] )

Result:

a
b
b
b
a
b
a
b

Now you can iterate over your indices to check if they are equal to the previous.

win = [i for i in chars]      # Convert chars string to a list of chars
last = ''                     # Create a variable to hold our last result
for i in win:
    if i != last:
        print(i)
    last = i                  # Set last to equal the last char iterated

Result:

a
b
a
b
a
b
a

Or if you want to print them out in a single string...

win = [i for i in chars]      # Convert chars string to a list of chars
last = ''                     # Create a variable to hold our last result
newchars = ''
for i in win:
    if i != last:
        newchars += i
    last = i                  # Set last to equal the last char iterated
print(newchars)

Result

abababa

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1121486

You are asking several for loops to all iterate over the same, single iterator. You did not create copies, they share one object.

The outer loop advances the charsnum object by one step, then the next for loop advances it once to start its iteration, and so on. The innermost for loop takes the remaining items to iterate over, and by the time you go back up to the for z loop there is nothing left to iterate over.

You can do the same thing, advancing the iterator like for does, with the next() function:

>>> chars = 'abbbababa'
>>> charsnum = enumerate(chars)
>>> i = next(charsnum)
>>> j = next(charsnum)
>>> z = next(charsnum)
>>> k = next(charsnum)
>>> i, j, z, k
((0, 'a'), (1, 'b'), (2, 'b'), (3, 'b'))
>>> next(charsnum)  # next k value in the innermost loop
(4, 'a')
>>> # etc. etc.

You could create separate enumerate() objects for each for loop:

for i in enumerate(chars):
    for j in enumerate(chars):
        for z in enumerate(chars):
            for k in enumerate(chars):
                print(i,j,z,k)

but that's just more work than you need. For nested loops repeating the same iterable, use itertools.product() and tell it to repeat; it'll keep copies as needed:

from itertools import product

for i, j, z, k in product(enumerate(chars), repeat=4):
    print(i, j, z, k)

This won't eliminate repeated characters, however; this produces the cartesian product of 4 (index, char) tuples out of all possible such tuples from your char string.

You probably want to create permutations form the unique letters, and string out the patterns those make into something the same length:

from itertools import permutations

for pattern in permutations(set(chars)):
    repeat = (len(chars) + 1) // len(pattern)
    result = (''.join(pattern) * repeat)[:len(chars)]
    print(result)

This produces

babababab
ababababa

Upvotes: 4

Arthur Gouveia
Arthur Gouveia

Reputation: 744

The "problem" is not at the for loops, but at charsnum. The object charsnum is a generator that yelds the next value everytime it is called.

In the first for loop (for j in charsnum) it yelds the first item in chars but in the inner loop (for z in charsnum) charsnum will yeld the next item in chars. So this inner loop will never access the first item in chars.

Upvotes: 0

Related Questions