I have a task to rearrange a sentence with the first name middle initial and last name to last first middle. I don't know how to do this without a stated search or how to make a index. Ive tried it with finding a space between but I don't know how I would rearrange doing this. This is what I have but it doesn't work. If I could get help defining each part I think I could do the rest on my own.
name = input("Enter a name like 'First I. Last: ")
index = name.find(" ")
rearranged = name[3:index]
If you're on Python 3.8+, you should be able to use it like this:
name = 'John C. Smith'
rearranged_name = ' '.join([(word := name.split(' '))[2], *word[:2]])
print(rearranged_name)
Note that in the above, you could also write out *word[:2] like word[0], word[1] if you prefer to be more explicit.
Output:
Smith John C.
If you're using an earlier version than 3.8, the following alternative should still work for your use case (adapted from a comment by #TheLazyScripter).
*rest, last = name.split(' ')
rearranged_name = ' '.join([last, *rest])
Where *rest can also be reworded as two separate variables - first, mi.
If you expect an exact number of fields, you could assign them directly to names
first, middle_i, last = input("Enter a name like 'First I. Last': ").split()
However, you'll probably find it better/easier to use a regular expression to let the fields be optional or write some other custom parser
import re
name = input("Enter a name like 'First I. Last': ")
match = re.match(r"(?P<first>\w+) (?:(?P<middle>\w\.) )?(?P<last>\w+)", name)
if not match:
raise ValueError(f"name is invalid: {name}")
# match.groupdict() is a dict with the members named in it now
>>> name = input("Enter a name like 'First I. Last': ")
Enter a name like 'First I. Last': a b. c
>>> name
'a b. c'
>>> match = re.match(r"(?P<first>\w+) (?:(?P<middle>\w\.) )?(?P<last>\w+)", name)
>>> match.groupdict()
{'first': 'a', 'middle': 'b.', 'last': 'c'}
...
>>> name = "foo bar"
...
>>> match.groupdict()
{'first': 'foo', 'middle': None, 'last': 'bar'}
Related
Using:
cur.execute(SQL)
response= cur.fetchall() //response is a LOB object
names = response[0][0].read()
i have following SQL response as String names:
'Mike':'Mike'
'John':'John'
'Mike/B':'Mike/B'
As you can see it comes formatted. It is actualy formatted like:\\'Mike\\':\\'Mike\\'\n\\'John\\'... and so on
in order to check if for example Mike is inside list at least one time (i don't care how many times but at least one time)
I would like to have something like that:
l = ['Mike', 'Mike', 'John', 'John', 'Mike/B', 'Mike/B'],
so i could simply iterate over the list and ask
for name in l:
'Mike' == name:
do something
Any Ideas how i could do that?
Many thanks
Edit:
When i do:
list = names.split()
I receive the list which is nearly how i want it, but the elements inside look still like this!!!:
list = ['\\'Mike\\':\\'Mike\\", ...]
names = ['\\'Mike\\':\\'Mike\\", ...]
for name in names:
if "Mike" in name:
print "Mike is here"
The \\' business is caused by mysql escaping the '
if you have a list of names try this:
my_names = ["Tom", "Dick", "Harry"]
names = ['\\'Mike\\':\\'Mike\\", ...]
for name in names:
for my_name in my_names:
if myname in name:
print myname, " is here"
import re
pattern = re.compile(r"[\n\\:']+")
list_of_names = pattern.split(names)
# ['', 'Mike', 'Mike', 'John', 'John', 'Mike/B', '']
# Quick-tip: Try not to name a list with "list" as "list" is a built-in
You can keep your results this way or do a final cleanup to remove empty strings
clean_list = list(filter(lambda x: x!='', list_of_names))
Okay, so I have the following piece of code.
out = out + re.sub('\{\{([A-z]+)\}\}', values[re.search('\{\{([A-z]+)\}\}',item).group().strip('{}')],item) + " "
Or, more broken down:
out = out + re.sub(
'\{\{([A-z]+)\}\}',
values[
re.search(
'\{\{([A-z]+)\}\}',
item
).group().strip('{}')
],
item
) + " "
So, basically, if you give it a string which contains {{reference}}, it will find instances of that, and replace them with the given reference. The issue with it in it's current form is that it can only work based on the first reference. For example, say my values dictionary was
values = {
'bob': 'steve',
'foo': 'bar'
}
and we passed it the string
item = 'this is a test string for {{bob}}, made using {{foo}}'
I want it to put into out
'this is a test string for steve, made using bar'
but what it currently outputs is
'this is a test string for steve, made using steve'
How can I change the code such that it takes into account the position in the loop.
It should be noted, that doing a word split would not work, as the code needs to work even if the input is {{foo}}{{steve}}
I got the output using the following code,
replace_dict = { 'bob': 'steve','foo': 'bar'}
item = 'this is a test string for {{foo}}, made using {{steve}}'
replace_lst = re.findall('\{\{([A-z]+)\}\}', item)
out = ''
for r in replace_lst:
if r in replace_dict:
item = item.replace('{{' + r + '}}', replace_dict[r])
print item
How's this?
import re
values = {
'bob': 'steve',
'foo': 'bar'
}
item = 'this is a test string for {{bob}}, made using {{foo}}'
pat = re.compile(r'\{\{(.*?)\}\}')
fields = pat.split(item)
fields[1] = values[fields[1]]
fields[3] = values[fields[3]]
print ''.join(fields)
If you could change the format of reference from {{reference}} to {reference}, you could achieve your needs just with format method (instead of using regex):
values = {
'bob': 'steve',
'foo': 'bar'
}
item = 'this is a test string for {bob}, made using {foo}'
print(item.format(**values))
# prints: this is a test string for steve, made using bar
In your code, re.search will start looking from the beginning of the string each time you call it, thus always returning the first match {{bob}}.
You can access the match object you are currently replacing by passing a function as replacement to re.sub:
values = { 'bob': 'steve','foo': 'bar'}
item = 'this is a test string for {{bob}}, made using {{foo}}'
pattern = r'{{([A-Za-z]+)}}'
# replacement function
def get_value(match):
return values[match.group(1)]
result = re.sub(pattern, get_value, item)
# print result => 'this is a test string for steve, made using bar'
I wish to let the user ask a simple question, so I can extract a few standard elements from the string entered.
Examples of strings to be entered:
Who is the director of The Dark Knight?
What is the capital of China?
Who is the president of USA?
As you can see sometimes it is "Who", sometimes it is "What". I'm most likely looking for the "|" operator. I'll need to extract two things from these strings. The word after "the" and before "of", as well as the word after "of".
For example:
1st sentence: I wish to extract "director" and place it in a variable called Relation, and extract "The Dark Knight" and place it in a variable called Concept.
Desired output:
RelationVar = "director"
ConceptVar = "The Dark Knight"
2nd sentence: I wish to extract "capital", assign it to variable "Relation".....and extract "China" and place it in variable "Concept".
RelationVar = "capital"
ConceptVar = "China"
Any ideas on how to use the re.match function? or any other method?
You're correct that you want to use | for who/what. The rest of the regex is very simple, the group names are there for clarity but you could use r"(?:Who|What) is the (.+) of (.+)[?]" instead.
>>> r = r"(?:Who|What) is the (?P<RelationVar>.+) of (?P<ConceptVar>.+)[?]"
>>> l = ['Who is the director of The Dark Knight?', 'What is the capital of China?', 'Who is the president of USA?']
>>> [re.match(r, i).groupdict() for i in l]
[{'RelationVar': 'director', 'ConceptVar': 'The Dark Knight'}, {'RelationVar': 'capital', 'ConceptVar': 'China'}, {'RelationVar': 'president', 'ConceptVar': 'USA'}]
Change (?:Who|What) to (Who|What) if you also want to capture whether the question uses who or what.
Actually extracting the data and assigning it to variables is very simple:
>>> m = re.match(r, "What is the capital of China?")
>>> d = m.groupdict()
>>> relation_var = d["RelationVar"]
>>> concept_var = d["ConceptVar"]
>>> relation_var
'capital'
>>> concept_var
'China'
Here is the script, you can simply use | to optional match one inside the brackets.
This worked fine for me
import re
list = ['Who is the director of The Dark Knight?','What is the capital of China?','Who is the president of USA?']
for string in list:
a = re.compile(r'(What|Who) is the (.+) of (.+)')
nodes = a.findall(string);
Relation = nodes[0][0]
Concept = nodes[0][1]
print Relation
print Concept
print '----'
Best Regards:)
If I have a string s = "Name: John, Name: Abby, Name: Kate". How do I extract everything in between Name: and ,. So I'd want to have an array a = John, Abby, Kate
Thanks!
No need for a regex:
>>> s = "Name: John, Name: Abby, Name: Kate"
>>> [x[len('Name: '):] for x in s.split(', ')]
['John', 'Abby', 'Kate']
Or even:
>>> prefix = 'Name: '
>>> s[len(prefix):].split(', ' + prefix)
['John', 'Abby', 'Kate']
Now if you still think a regex is more appropriate:
>>> import re
>>> re.findall('Name:\s+([^,]*)', s)
['John', 'Abby', 'Kate']
The interesting question is how you would choose among the many ways to do this in Python. The answer using "split" is nice if you're confident that the format will be exact. If you would like some protection from minor format changes, a regular expression might be useful. You should think through what parts of the format are most likely to be stable, and capture those in your regular expression, while leaving flexibility for the others. Here is an example that assumes that the names are alphabetic, and that the word "Name" and the colon are stable:
import re
s = "Name: John, Name: Abby, Name: Kate"
names = [i.group(1) for i in re.finditer("Name:\s+([A-Za-z]*)", s)]
print names
You might instead want to allow for hyphens or other characters inside a name; you can do so by changing the text inside [A-Za-z].
A good page about Python regular expressions with lots of examples is http://docs.python.org/howto/regex.html.
Few more ways to do it
>>> s
'Name: John, Name: Abby, Name: Kate'
Method 1:
>>> [x.strip() for x in s.split("Name:")[1:]]
['John,', 'Abby,', 'Kate']
Method 2:
>>> [x.rsplit(":",1)[-1].strip() for x in s.split(",")]
['John', 'Abby', 'Kate']
Method 3:
>>> [x.strip() for x in re.findall(":([^,]*)",s)]
['John', 'Abby', 'Kate']
Method 4:
>>> [x.strip() for x in s.replace('Name:','').split(',')]
['John', 'Abby', 'Kate']
Also note, how I always consistently applied strip which makes sense if their can be multiple spaces between 'Name:' token and the actual Name.
Method 2 and 3 can be used in a more generalized way.
How to match exact string/word while searching a list. I have tried, but its not correct. below I have given the sample list, my code and the test results
list = ['Hi, friend', 'can you help me?']
my code
dic=dict()
for item in list:
for word in item.split():
dic.setdefault(word, list()).append(item)
print dic.get(s)
test results:
s = "can" ~ expected output: 'can you help me?' ~ output I get: 'can you help me?'
s = "you" ~ expected output: *nothing* ~ output I get: 'can you help me?'
s = "Hi," ~ expected output: 'Hi, friend' ~ output I get: 'Hi, friend'
s = "friend" ~ expected output: *nothing* ~ output I get: 'Hi, friend'
My list contains 1500 strings. Anybody can help me??
Looks like you need a map of sentences and their starting word, so you don't need to map all words in that sentence but only the first one.
from collections import defaultdict
sentences = ['Hi, friend', 'can you help me?']
start_sentence_map = defaultdict(list)
for sentence in sentences:
start = sentence.split()[0]
start_sentence_map[start].append(sentence)
for s in ["can", "you", "Hi,", "friend"]:
print s,":",start_sentence_map.get(s)
output:
can : ['can you help me?']
you : None
Hi, : ['Hi, friend']
friend : None
Also note few things from the code above
Don't use name list as name of variable because python uses it for list class
Use default dict which makes it easy to directly add entries to dictionary instead of first adding a default entry
Better descriptive names instead of mylist, or dic
In case if you just want to see if the sentence starts with a given words you can try startswith if you don;t want the searched word to be at word boundary or split()[0] if you want it to match at word boundary. As an example
>>> def foo(s): # # word boundary
return [x for x in l if x.split()[0]==s]
>>> def bar(s): # Prefix
return [x for x in l if x.startswith(s)]
Also refrain from overlaying python global name-space like what you did when you named your list as list. I have called it l in my example.