Trying to insert " _ " before uppercase letters but it inserts more than once.
Instead of ["h", "e", "l", "l", "o", " _ ", "W", "o", "l", "r", "d"] it prints ['h', 'e', 'l', 'l', 'o', ' _ ', ' _ ', ' _ ', ' _ ', 'W', 'o', 'l', 'r', 'd']
new = ["h", "e", "l", "l", "o", "W", "o", "r", "l", "d"]
for i in range(len(new)):
print(i)
if new[i].isupper():
new.insert(i, "_")
print(new)
CodePudding user response:
Because after you insert
'_'
at index i
, the uppercase letter (W
) is moved to the right and thus gets the index i 1
. Now the for loop iteration completes, and i
gets incremented and becomes i 1
, but guess what is at index i 1
? (Hint: W
) So, this is a cycle that only exhausts when the for loop iterates len(new)
times. Below is what the execution might look like:
- (i=0): new[i] is 'h'
- (i=1): new[i] is 'e'
- (i=2): new[i] is 'l'
- (i=3): new[i] is 'l'
- (i=4): new[i] is 'o'
- (i=5): new[i] is 'W' -->
insert '_'
--> 'W' moves tonew[i 1]
- (i=6): new[i] is 'W' -->
insert '_'
--> and this pattern repeats
A simple solution would be to run backwards. As now, insert '_'
will push 'W' to the right, while we are moving to the left; therefore, we won't end up in the cycle like before.
new = ["h", "e", "l", "l", "o", "W", "o", "r", "l", "d"]
start = len(new) - 1 # last element
end = -1 # one prior to the first element
# remember, range end is non-inclusive,
# so it goes till index 0
step = -1 # decrement to move backwards
for i in range(start, end, step):
if new[i].isupper():
new.insert(i, "_")
print(new)
CodePudding user response:
You can create a new list:
new = ["h", "e", "l", "l", "o", "W", "o", "r", "l", "d"]
result = []
for i in range(len(new)):
if new[i].isupper():
result.append("_")
result.append(new[i])
print(result)
CodePudding user response:
In your code, each call to new.insert(i, "_")
changes new
so that the uppercase letter that was previously at index i
is now a index i 1
, since you have just inserted the character _
at index i
and pushed he uppercase letter (and every item that comes after it in the list new
) one position higher.
One way to fix this would be to loop through new
in reverse order using python's built-in function reversed()
:
new = ["h", "e", "l", "l", "o", "W", "o", "r", "l", "d"]
for i in reversed(range(len(new))):
#print(i)
if new[i].isupper():
new.insert(i, "_")
print(new)
Now, after examining the character at index i
, detecting that it's uppercase, and inserting _
at i
, the next loop iteration examines the character at position i - 1
, which was unaffected by the prior iteration's call to new.insert(i, "_")
.
Output:
['h', 'e', 'l', 'l', 'o', '_', 'W', 'o', 'r', 'l', 'd']