Separate initials from full name input in python without using split - python

EDIT This was my first post and I completely forgot to show what I had already tried. I wasn't looking for a complete program, just suggestions on methods I could use to concatenate initials. EDIT
I need to create a program that allows a user to input their full name and only prints the initials. This must be done WITHOUT USING .SPLIT OR LISTS
From my hw:
Write a program that gets a string of a person's full name – first, middle, and last name and then displays their initials.
Create a function getInitials().
>>>Enter your full name: James Tiberias Kirk
>>>J.T.K.

Try this one:
n = input('Enter your full name:')
name = ''
for i,j in enumerate(n):
if i == 0:
name+=(j+'.')
elif j == ' ':
name += (n[i+1]+'.')
print(name)
And this is as method:
def getinitials(n):
name = ''
for i,j in enumerate(n):
if i == 0:
name+=(j+'.')
elif j == ' ':
name += (n[i+1]+'.')
return name
print(getinitials(input('Enter your number:')))
Output:
Enter your full name:James Tiberias Kirk
J.T.K.

I ended up figuring it out thanks to all your responses. Our teacher wanted us to only use the narrow scope of what we've learned in class so there was pretty much only one way I would be allowed to write it. I ended up coming up with this:
def getInitials():
fullName=input("Enter your full name:")
initials=''
for ch in fullName:
if ch.isupper():
initials+=ch
initials=str(initials)+"."
print (initials)
if __name__=="__getInitials__":
getInitials()
getInitials()

Assuming you won't deal with names like DeFranco or McDonald, you can iterate over the string and append encountered capital letters (that is, ord('A') <= ord(char) <= ord('Z')) with a dot to your result.
Similar approach that should work on most cases is to append the first character, then look for spaces and append a character next to them.

One solution that technically doesn't use a list:
'.'.join(i for i in x if i.isupper())+'.'
...which uses a generator expression, but that may be closer to a list than the spirit of the assignment. As in the other answer, it fails if a name has more than one capital in the name (McGregor, etc.)

You could use a regex, while returning a generator statement from your getInitials() function, therefore you technically avoid using both split() and a list:
import re
def getInitials(x):
return '.'.join(i for i in re.findall(r'^[A-Z]|(?<=\s)[A-Z]', x)) + '.'
out = getInitials('James Tiberias Kirk McGregor')
Yields:
J.T.K.M.
Note that this method works for names with more than one capital letter per name/word.

Related

Input Name with space with validation

I am using the .isalpha function to take an input of a name. It is working but whenever i put on space between name for example a full name John Doe It gives me error.
What ive Tried so far
while not name.isalpha():
print('Entered Name is invalid')
name = input('Please Enter Your Name Sir: ')
if name.isalpha() or name.isspace():
print('Hello Mr.' + name)
select_mmenu('main-menu.txt')
I've tried combining .isalpha and .isspace but it seems not to be working. Need the most simple way to solve this trick
isalpha tests that each member of the string is a letter. isspace tests that each member of the string is a whitespace character. Neither of those is what you want.
Instead you could do:
if all(lett.isalpha() or lett.isspace() for lett in name):
which will pass if every letter is EITHER a letter or a space. Alternatively you can match a regular expression:
import re # at the top of your module
if re.match(r"[\s\w]+$", name):
which is arguably cleaner, and certainly more powerful. The square brackets denote a character class, \s is all whitespaces and \w is all word character, the + means "matches 1 or more times," and the $ is the end of string. [\s\w]+$ then means "one or more characters that are either whitespace or word characters, and nothing afterwards.
It will certainly give you an error because the method isalpha() checks whether the string consists of alphabetic characters only. So if you put a space, the result will return false instead of true, and you will get an error.
Thankyou for the answers. I got it solved without using all() function. I just solved it with simplest basic Python loops
Thankyou Adam Smith because of your answer i got this idea to solve it through that method
con = False
while con!=True:
l=0
strs = input('Enter your Name: ')
for i in strs:
if i.isalpha() or i.isspace():
l += 1
if l == len(strs):
con = True
break
else:
print('Wrong Input')
if con==True:
print(strs)
In this code its basically counting the input lenght and alphabets and space lenght if it match it works. else the while loop continue.

Python coding flaw for making acronyms

The code written below should give results like below. For example, if input is ' Lion head and Snake tail', output should be - 'LHAST'.
Instead the result is 'LLLLL'. Please check my code. If possible please suggest better practice and help me with better code.
Code is as follows:
#ask for Input
name = input('Input words to make acroname :')
#make all in caps
name = name.upper()
#turn them in list
listname = name.split()
#cycle through
for namee in listname:
#Get the first letter & type in same line
print(name[0],end="")
print()
input (' press a key to move out' )
You may correct your code. Instead of print(name[0]) you should use print(namee[0]) as you want to print the first letter of the word, not the original name.
A good practice is to name the variables the more descriptive you can so as to avoid such typos.
If you want to print the acronym in same line I would suggest to use below code to get variable acronym with the desired output:
phrase = raw_input('Input words to make acronym:')
phrase = phrase.upper()
list_words = phrase.split()
acronym = [word[0] for word in list_words]
acronym = "".join(acronym)
print acronym
You could use str.join with a generator-expression for a one-line solution to the problem:
>>> name = "Lion head and Snake tail"
>>> ''.join(i[0].upper() for i in name.split())
'LHAST'
why?
Well if we start from inside the generator, we are iterating through name.split(). The .split method of a str returns a list of all the different strings which have been found by splitting on what is passed into the method. The default character is a space and since we want the words, this is fine for us.
We then say that for each word i in this list, take the first character from the string with: i[0]. We then convert this to upper case with str.upper().
Then, the final step is to join all these characters together and that is done with the str.join method.
Simply:
print ''.join([P[0] for P in input('Input words to make acroname :').upper().split()])
Use input('') for python 3 and raw_input('') for python 2

Python code, .rstrip isn't working?

I've searched answers on here and tried implementing them but I think that there is some tiny detail I'm missing. I have a very short python code for a program that is supposed to return the initials with periods of a persons input(for their full name). So for example, input is Atticus Leonard Beasley and output should be
A.L.B.
but instead I'm getting:
A.
L.
B.
Here's my code:
def main():
full_name = input("Enter your first, middle, and last name: ")
for ch in full_name:
if ch.isupper():
ch = ch.rstrip('\n')
print (ch,'.', sep='')
main()
FYI, you can do this using split and join:
def main():
full_name = input("Enter your first, middle, and last name: ")
initials = []
for name in full_name.split():
initials.append(name[0])
print('.'.join(initials) + '.')
main()
Or using list comprehension:
def main():
full_name = input("Enter your first, middle, and last name: ")
print('.'.join(name[0] for name in full_name.split())+'.')
main()
I think you can do that in a easier and "more pythonic" way.
full_name = input("Enter your first, middle, and last name: ")
print(''.join([ch[0].upper() + '.' for ch in full_name.split()]))
EXPLANATIONS
Instead of doing a for loop over each letters of the name, you can use split() function to be sure to took care of every words without the extra spaces.
sentence = "hello world"
for ch in sentence.split():
print(ch) # hello
break
Now, you try to verify if the first letter is an uppercase, but if the user enter his name without uppercase, your function does not work. An easier solution will be to extract the first letter of the word ch[0] and automatically add an uppercase: ch[0].upper()
Maybe the one-liner solution is confusing, but most of the python developers use list comprehension over for loops when the solution is easily readable.
EDIT
One more thing, even if you are writing a simple function such as print the initials of a name, you should always write tests accordingly.
A good way to start is to use doctests because it forces you to describe what your function does. Even if you think it's a waste of times, it helps to overcome many problems when your program is getting bigger. I'd be please to help you if you want to try to write your first doctest

split string update numbers only

I have a function using raw_input getting a sentence from user. Then my second function splits the sentence so I am only trying to update the numbers on the sentence. This is the split sentence:
['You', 'are', '42', 'this', 'year']
I am trying to update 42 to 43 do a return and print 'You are 43 this year'
I am able to pull the number by using isdigit() but I can't increase it. This is what I have so far:
def GetDigits(sentence):
for i in sentence:
if i.isindigit():
i = i +1
return sentence
Numbers in Python are immutable objects, so when you do i = i+1, you are creating a new object. This new object is not part of your original sentence object. Also, '42' is a string. You can't apply numeric add operation on it. You need to convert it to an integer first.
This is what you need -
def GetDigits(sentence):
for idx, value in enumerate(sentence):
if value.isdigit():
sentence[idx] = int(value) +1
return sentence
There is a built in method for strings that would be much better for this, format()
age = raw_input('How old are you?')
sentence = 'You are {} this year'
print(sentence.format(age))
If you need to update it you can:
print(sentence.format(int(age) + 1))
Alternatively as function utilizing a generator comprehension:
def get_digits(sentence):
return ' '.join(str(int(word) + 1) if word.isdigit() else word for word in sentence.split())
Another hacky way through regex using re module,
import re
sentence = input("Enter the sentence : \n")
def GetDigits(sentence):
L = []
for i in sentence.split():
if re.match(r'\d+$', i):
i = int(i)+1
L.append(str(i))
else:
L.append(i)
sentence = ' '.join(L)
return(sentence)
print(GetDigits(sentence))
Output:
Enter the sentence :
You are 42 this year
You are 43 this year
You're trying to add 1 to a string, as '42' isn't the same as 42.
You need to change '42' to an int first using int(v), then increase it.
def GetDigits(sentence):
for i, v in enumerate(sentence):
if v.isdigit():
sentence[i] = str(int(v) + 1)
return sentence
The key issue here is that you're trying to find a function that lets you know when it's safe/correct to convert a string to an int—but there is no such function. There are various approximations, but the simplest thing to do is just try to convert the string. This is a general principle in Python, EAFP: Easier to Ask Forgiveness than Permission. The language has been designed around the fact that the way to check whether something will work is to just do it, then handle the case where it didn't work (normally meaning an exception). Trying to fight that design is just going to make your life harder.
But that's not the only issue; there are multiple problems here.
isindigit isn't a method of strings. Maybe you meant isdigit?
isdigit doesn't give you the right answer for, say, -3—or, for that matter, integers in non-Western scripts (which may return true for isdigit but not actually be interpretable as integers by Python).
Just because i is a string representing an integer doesn't mean it's an integer; it's still a string, and i + 1 is still a TypeError. You need to call int(i) to get its value as a number.
Just reassigning to i doesn't affect sentence at all. All you're doing is making the local variable i into a name for a different value. You need to do something with that i—either build a new sentence, or modify the sentence in-place (e.g., by using enumerate to keep track of the index, so you can do sentence[index] = …).
While it isn't clear what you're doing with the results, I'll bet you actually want to get strings back, not a mix of strings and integers, so you'll probably want to convert back to str after adding 1.
So, what you want is something like this:
def GetDigits(sentence):
new_sentence = []
for i in sentence:
try:
i = str(int(i) + 1)
except ValueError:
pass
new_sentence.append(i)
return new_sentence
However, this might be a little too clever as written. If i doesn't represent an integer, int(i) will raise a ValueError, meaning i is still referring to the original string, which we add to new_sentence. Otherwise, we'll convert it to an integer, add 1, convert back to a string, and make i refer to this new string, which we add to new_sentence. If you don't understand why new_sentence.append(i) always does the right thing, you should rewrite it more explicitly.

Python String Replace Behaving Weirdly

I am trying to get users who are mentioned in an article. That is, words starting with # symbol and then wrap < and > around them.
WHAT I TRIED:
def getUsers(content):
users = []
l = content.split(' ')
for user in l:
if user.startswith('#'):
users.append(user)
return users
old_string = "Getting and replacing mentions of users. #me #mentee #you #your #us #usa #wo #world #word #wonderland"
users = getUsers(old_string)
new_array = old_string.split(' ')
for mention in new_array:
for user in users:
if mention == user and len(mention) == len(user):
old_string = old_string.replace(mention, '<' + user + '>')
print old_string
print users
The code is behaving funny. It wraps words starting with the same alphabets and even truncate subsequent as shown in the print below:
RESULT:
Getting and replacing mentions of users. <#me> <#me>ntee <#you> <#you>r <#us> <#us>a <#wo> <#wo>rld <#wo>rd <#wo>nderland
['#me', '#mentee', '#you', '#your', '#us', '#usa', '#wo', '#world', '#word', '#wonderland']
EXPECTED RESULT:
Getting and replacing mentions of users. <#me> <#mentee> <#you> <#your> <#us> <#usa> <#wo> <#world> <#word> <#wonderland>
['#me', '#mentee', '#you', '#your', '#us', '#usa', '#wo', '#world', '#word', '#wonderland']
Process finished with exit code 0
Why is this happening and how can do this the right way?
Why this happens: When you split the string, you put a lot of checks in to make sure you are looking at the right user e.g. you have #me and #mentee - so for user me, it will match the first, and not the second.
However, when you do replace, you are doing replace on the whole string - so when you say to replace e.g. #me with <#me>, it doesn't know anything about your careful split - it's just going to look for #me in the string and replace it. So #mentee ALSO contains #me, and will get replaced.
Two (well, three) choices: One is to add the spaced around it, to gate it (like #parchment wrote).
Second is to use your split: Instead of replacing the original string, replace the local piece. The simplest way to do this is with enumerate:
new_array = old_string.split(' ')
for index, mention in enumerate(new_array):
for user in users:
if mention == user and len(mention) == len(user):
#We won't replace this in old_string, we'll replace the current entry
#old_string = old_string.replace(a, '<' + user + '>')
new_array[index] = '<%s>'%user
new_string = ' '.join(new_array)
Third way... this is a bit more complex, but what you really want is for any instance of '#anything' to be replaced with <#anything> (perhaps with whitespace?). You can do this in one shot with re.sub:
new_string = re.sub(r'(#\w+)', r'<\g<0>>', old_string)
My previous answer was based entirely on correcting the problems in your current code. But, there is a better way to do this, which is using regular expressions.
import re
oldstring = re.sub(r'(#\w+)\b', r'<\1>', oldstring)
For more information, see the documentation on the re module.
Because #me occurs first in your array, your code replaces the #me in #mentee.
Simplest way to fix that is to add a space after the username that you want to be replaced:
old_string = old_string.replace(a + ' ', '<' + user + '> ')
# I added space here ^ and here ^
A new problem occurs, though. The last word is not wrapped, because there's no space after it. A very simple way to fix it would be:
oldstring = oldstring + ' '
for mention in ... # Your loop
oldstring = oldstring[:-1]
This should work, as long as there isn't any punctuation (like commas) next to the usernames.
def wrapUsers(content):
L = content.split()
newL = []
for word in L:
if word.startswith('#'): word = '<'+word+'>'
newL.append(word)
return " ".join(newL)

Categories

Resources