Reputation: 1
I am a beginner learning python, trying to accomplish the following:
Given two strings of equal length, e.g:
string_1 = 'Hello' string_2 = 'World' print them vertically side by side, with a space between each character:
H W
e o
l r
l l
o d
however I am encountering an issue with my code where the first and second 'l' in 'Hello' are being treated as the same letter, which is leading to some issues in output
here is my code:
string1 = 'Hello'
string2 = 'World'
indx = ''
for letter in string1:
indx = int(string1.index(letter))
print(letter + ' ' + string2[indx])
it ends up giving the result as shown(area of concern bolded for easier viewing):
H W
e o
l **r**
l **r**
o d
instead of:
H W
e o
l **r**
l **l**
o d
My question is how I can modify the code such that it can distinguish between the 2 'l's in 'Hello', or if my code was entirely wrong to begin with. Am not sure how to proceed with this
As I am just starting out I am not sure how to deal with this issue and hope to get some advice on how to rectify the issue and improve the code.Thanks.
Upvotes: -1
Views: 78
Reputation: 27316
As @Grismar has rightly pointed out, your code will not work if either of the strings have duplicated letters.
What you really want to do is iterate over the strings "side-by-side". The built-in zip function will work if both strings are of equal length. For strings of equal or differing lengths you could use itertools.zip_longest
Try this:
from itertools import zip_longest
string1 = 'Orange'
string2 = 'Grapefruit'
for p in zip_longest(string1, string2, fillvalue=" "):
print(*p)
Output:
O G
r r
a a
n p
g e
e f
r
u
i
t
If, for some reason, you're not comfortable with zip_longest() then you could even write something that will handle an arbitrary number of strings.
Something like this:
from collections.abc import Iterator
def yc(s: str) -> Iterator[str]:
yield from s
while True:
yield " "
def vprint(*s: str) -> None:
gf = [yc(a) for a in s]
for _ in range(max(map(len, s))):
print(*(next(g) for g in gf))
vprint("Orange", "Grapefruit", "Tomato", "Banana", "Lemon")
Output:
O G T B L
r r o a e
a a m n m
n p a a o
g e t n n
e f o a
r
u
i
t
Upvotes: 3
Reputation: 31396
You are using the position of the first occurrence of a letter in the first string to index the second string. However, since the letter appears twice, you get the same index every time you try. You stated "I want indx
to take on the placement value of each letter?" which is fair, and there's several ways to achieve that.
For all those solutions though, you have to consider these scenarios:
string1
could be longer than string2
string1
could be shorter than string2
Here are some possible solutions:
for indx in range(0, len(string1)
) like @johngordon's answer suggestsstring1 = 'Hello'
string2 = 'World'
for idx in range(len(string1)):
print(string1[idx], string2[idx])
This causes an error if string2
is shorter, and only prints the first letters from string2
if it is longer.
string1
, you want the accompanying index which can be done with enumerate()
:string1 = 'Hello'
string2 = 'World'
for indx, letter in enumerate(string1):
print(letter + ' ' + string2[indx])
This has the same behaviour - you get an error if string2 is shorter, and only the first first few letters matching string1
's length if it is longer.
string1
, you can just get the next letters from string2
and keep track of it as you go:string1 = 'Hello'
string2 = 'World'
indx = 0 # note that '' is not a very good value, since you need an integer, not a string
for letter in string1:
print(letter + ' ' + string2[indx])
indx += 1 # increase the index so that it has the right value for the next iteration
Again, the same problem.
zip()
to get a letter from each string pairwise:string1 = 'Hello'
string2 = 'World'
for letter1, letter2 in zip(string1, string2):
print(letter1 + ' ' + letter2)
This never causes an error, but you only get the number of characters that matches the shortest length, so you're not guaranteed to get all the letters from string1
if string2
is shorter.
If you always want all the letters from both strings, and blanks for the other, you could do something like:
string1 = 'Hello'
string2 = 'World'
longest = max(len(string1), len(string2))
for indx in range(longest):
letter1 = ' ' if indx >= len(string1) else string1[indx]
letter2 = ' ' if indx >= len(string2) else string2[indx]
print(letter1 + ' ' + letter2)
By the way, shortening an already short name like index
to indx
is generally a bad idea. Pick a name that's descriptive and doesn't require someone to remember how you decided to spell it - index
would be better. If you can't use index
because something else already used that, consider putting your code in a separate function and call it. That makes the code more reusable (especially if you do a good job with nice function arguments) and organised.
Upvotes: -1
Reputation: 33351
In this case you probably want to iterate over the positions in the string, instead of the letters.
for idx in range(len(string1)):
print(string1[idx], string2[idx])
Upvotes: 0