def handler_users_answ(coze, res, type, source):
if res:
if res.getType() == 'result':
aa=res.getQueryChildren()
if aa:
print 'workz1'
for x in aa:
m=x.getAttr('jid')
if m:
print m
so this code returns me the values like this:
roomname#domain.com/nickname1
roomname#domain.com/nickname2
and so on, but i want it to print the value after the '/' only.
like:
nickname1
nickname2
Thanks in advance.
You can use rpartition to get the part after the last \ in the string.
a = 'roomname#domain.com/nickname1'
b=a.split('/');
c=b[1];
You can use rsplit which will do the splitting form the right:
a = 'roomname#domain.com/nickname1'
try:
print a.rsplit('/')[1][1]
except IndexError:
print "No username was found"
I think that this is efficient and readable. If you really need it to be fast you can use rfind:
a = 'roomname#domain.com/nickname1'
index = a.rfind('/')
if index != -1:
print a[index+1:]
else:
print "No username was found"
To fully parse and validate the JID correctly, see this answer. There's a bunch of odd little edge cases that you might not expect.
Related
What's a cute way to do this in python?
Say we have a list of strings:
clean_be
clean_be_al
clean_fish_po
clean_po
and we want the output to be:
be
be_al
fish_po
po
Another approach which will work for all scenarios:
import re
data = ['clean_be',
'clean_be_al',
'clean_fish_po',
'clean_po', 'clean_a', 'clean_clean', 'clean_clean_1']
for item in data:
item = re.sub('^clean_', '', item)
print (item)
Output:
be
be_al
fish_po
po
a
clean
clean_1
Here is a possible solution that works with any prefix:
prefix = 'clean_'
result = [s[len(prefix):] if s.startswith(prefix) else s for s in lst]
You've merely provided minimal information on what you're trying to achieve, but the desired output for the 4 given inputs can be created via the following function:
def func(string):
return "_".join(string.split("_")[1:])
you can do this:
strlist = ['clean_be','clean_be_al','clean_fish_po','clean_po']
def func(myList:list, start:str):
ret = []
for element in myList:
ret.append(element.lstrip(start))
return ret
print(func(strlist, 'clean_'))
I hope, it was useful, Nohab
There are many ways to do based on what you have provided.
Apart from the above answers, you can do in this way too:
string = 'clean_be_al'
string = string.replace('clean_','',1)
This would remove the first occurrence of clean_ in the string.
Also if the first word is guaranteed to be 'clean', then you can try in this way too:
string = 'clean_be_al'
print(string[6:])
You can use lstrip to remove a prefix and rstrip to remove a suffix
line = "clean_be"
print(line.lstrip("clean_"))
Drawback:
lstrip([chars])
The [chars] argument is not a prefix; rather, all combinations of its values are stripped.
I have two different kinds of URLs in a list:
The first kind looks like this and starts with the word 'meldung':
meldung/xxxxx.html
The other kind starts with 'artikel':
artikel/xxxxx.html
I want to detect if a URL starts with 'meldung' or 'artikel' and then do different operations based on that. To achieve this I tired to use a loop with if and else conditions:
for line in r:
if re.match(r'^meldung/', line):
print('je')
else:
print('ne')
I also tried this with line.startswith():
for line in r:
if line.startswith('meldung/'):
print('je')
else:
print('ne')
But both methods dont work since the strings I am checking dont have any whitespaces.
How can I do this correctly?
You can just use the following, if the links are stored as strings within the list:
for line in r:
if ‘meldung’ in line:
print(‘je’)
else:
print(‘ne’)
What about this:
r = ['http://example.com/meldung/page1.html', 'http://example.com/artikel/page2.html']
for line in r:
url_tokens = line.split('/')
if url_tokens[-2] == 'meldung':
print(url_tokens[-1]) # the xxxxx.html part
elif url_tokens[-2] == 'artikel':
print('ne')
else:
print('something else')
you can do it using regex:
import re
def check(string):
if (re.search('^meldung|artikel*', string)):
print("je")
else:
print("ne")
for line in r:
check(line)
I have a list with different email formatting, which I want to unify all in one.
There are 2 types of email:
name.surname#dom
name.surname.extern#dom
My program allows the user to input emails, and to not have to enter "#dom" all the time (it's always the same one), what I've done is allowing the user to write name.surname or name.surname.e and then the script replaces those usernames with #dom or .extern#dom
The problem rises when I have all the mails in different formats stores in a list, and I want them to be filled to standards, so that if I have
["john.doe#dom", "john2.doe", "john3.doe.e","john4.doe.extern#dom"]
it all ends up looking like this
["john.doe#dom", "john2.doe#dom", "john3.doe.extern#dom","john4.doe.extern#dom"]
I have tried with list comprehensions, but all I got was three concatenations:
["%s.xtern#dom" % x for x in mails if x[-2:] == ".e"] +
["%s#dom" %x for x in mails if "#dom not in mails" and x[-2:] != ".e"] +
[x for x in mails if "#dom" in x]
I'm sure there's a better way that does not require me to do 3 list comprehensions and that does not require me to do
for i,v in enumerate(mails):
if "#dom" not in v:
mails[i] = "%s#dom" % v
etc.
You can use a string's endswith() method to determine what you need to do with the input:
mails = ["john.doe#dom", "john2.doe", "john3.doe.e","john4.doe.extern#dom"]
final_mails = []
for mail in mails:
if mail.endswith("#dom"):
# Use as-is if it ends with #dom.
final_mails.append(mail)
elif mail.endswith(".e"):
# Replace to extern#dom if it ends with .e
final_mails.append(mail.replace(".e", ".extern#dom"))
else:
# Add #dom on all other cases
final_mails.append("{}#dom".format(mail))
print final_mails
# Result: ['john.doe#dom', 'john2.doe#dom', 'john3.doe.extern#dom', 'john4.doe.extern#dom']
It might need more thorough checks to not accept things like #dom right in the middle of the name and whatnot. Hope that helps you out though!
Edit:
Just for fun, if you insist on a list comprehension:
mails = ["john.doe#dom", "john2.doe", "john3.doe.e","john4.doe.extern#dom"]
final_mails = ["{}#dom".format((mail.replace(".e", ".extern#dom")
if mail.endswith(".e") else mail).rstrip("#dom"))
for mail in mails]
print final_mails
# Result: ['john.doe#dom', 'john2.doe#dom', 'john3.doe.extern#dom', 'john4.doe.extern#dom']
Personally I find list comprehensions are best when they are short and readable, so I would stick with the first option.
Option without listcomprehensions:
maillist = ["john.doe#dom", "john2.doe", "john3.doe.e","john4.doe.extern#dom"]
for i in range(len(maillist)):
if "#" not in maillist[i]:
if maillist[i][-2:]== ".e":
maillist[i] += ("xtern#dom")
else:
maillist[i] += "#dom"
#Green Cell was faster than me and his answer seems to be correct. Here is a list comprehension that does the same thing :
mails = ["john.doe#dom", "john2.doe", "john3.doe.e","john4.doe.extern#dom"]
print mails
mails = [mail if mail.endswith("#dom") else mail.replace(".e", ".extern#dom") if mail.endswith(".e") else "{}#dom".format(mail) for mail in mails]
print mails
Which outputs :
['john.doe#dom', 'john2.doe', 'john3.doe.e', 'john4.doe.extern#dom']
['john.doe#dom', 'john2.doe#dom', 'john3.doe.extern#dom', 'john4.doe.extern#dom']
Hope this helps.
if you want a one-liner, combine list comprehension with multiple if/else statements:
first_list = ["john.doe#dom", "john2.doe", "john3.doe.e","john4.doe.extern#dom"]
second_list = [email + 'xtern#dom' if email.endswith(".e") else \
email if email.endswith("#dom") else "{}#dom".format(email) \
for email in first_list]
print second_list
Gives:
['john.doe#dom', 'john2.doe#dom', 'john3.doe.extern#dom', 'john4.doe.extern#dom']
I came with a different solution in the end: Declaring a help function.
def mailfy(mail):
if mail.endswith(".c"):
return mail[:-2] + "#dom"
...
mails = [mailfy(x) for x in mails]
def split_3(s):
s=s.split(".",1)
s_left=s[0]
s_right=s[1]
for words in s:
t=len(s[0])
return ("{s_left},{t},{s_right}").format(s_left=s_left,t=t,s_right=s_right)
#example: split_3('this is it.another one.')
#output='this is it,10,another one.'
#desired output= ('this is it', 10, ' another one.')
The task is to return the amount of contents in the string when the first "." appears. And then format it the way that you have the output you already see(Sentence until 1st "." , number of the contents until then, the remaining string
Like you see i already get the desired output, however i have to return it as a triple and i am not sure how to do that
I hope you can help me in this case.
you mean this?
return (s_left,t,s_right)
You can also assign to a tuple from the split, so the function becomes simpler:
def split_3(s):
s_left, s_right = s.split(".", 1)
t = len(s_left)
return (s_left, t, s_right)
I have to parse some numbers from file names that have no common logic. I want to use the python way of "try and thou shall be forgiven", or try-except structure. Now I have to add more than two cases. What is the correct way of doing this? I am now thinking either nested try's or try-except-pass, try-except-pass,... Which one would be better or something else? Factory method perhaps (how?)?
This has to be easily expandable in the future as there will be much more cases.
Below is what I want (does not work because only one exeption per try can exist):
try:
# first try
imNo = int(imBN.split('S0001')[-1].replace('.tif',''))
except:
# second try
imNo = int(imBN.split('S0001')[-1].replace('.tiff',''))
except:
# final try
imNo = int(imBN.split('_0_')[-1].replace('.tif',''))
Edit:
Wow, thanks for the answers, but no pattern matching please. My bad, put "some common logic" at the beginning (now changed to "no common logic", sorry about that). In the cases above patterns are pretty similar... let me add something completely different to make the point.
except:
if imBN.find('first') > 0: imNo = 1
if imBN.find('second') > 0: imNo = 2
if imBN.find('third') > 0: imNo = 3
...
You can extract the common structure and make a list of possible parameters:
tries = [
('S0001', '.tif'),
('S0001', '.tiff'),
('_0_', '.tif'),
]
for sep, subst in tries:
num = imBN.split(sep)[-1].replace(subst, '')
try:
imNo = int(num)
break
except ValueError:
pass
else:
raise ValueError, "String doesn't match any of the possible patterns"
Update in reaction to question edit
This technique can easily be adapted to arbitrary expressions by making use of lambdas:
def custom_func(imBN):
if 'first' in imBN: return 1
if 'second' in imBN: return 2
tries = [
lambda: int(imBN.split('S0001')[-1].replace('.tif','')),
lambda: int(imBN.split('S0001')[-1].replace('.tiff','')),
lambda: int(imBN.split('_0_')[-1].replace('.tif','')),
lambda: custom_func(imBN),
]
for expr in tries:
try:
result = expr()
break
except:
pass
else:
# error
In your specific case, a regular expression will get rid of the need to do these try-except blocks. Something like this might catch your cases:
>>> import re
>>> re.match('.*(S0001|_0_)([0-9]+)\..*$', 'something_0_1234.tiff').groups()
('_0_', '1234')
>>> re.match('.*(S0001|_0_)([0-9]+)\..*$', 'somethingS00011234.tif').groups()
('S0001', '1234')
>>> re.match('.*(S0001|_0_)([0-9]+)\..*$', 'somethingS00011234.tiff').groups()
('S0001', '1234')
For your question about the serial try-except blocks, Niklas B.'s answer is obviously a great one.
Edit:
What you are doing is called pattern matching, so why not use a pattern matching library? If the regex string is bothering you, there are cleaner ways to do it:
import re
matchers = []
sep = ['S0001', '_0_']
matchers.append(re.compile('^.*(' + '|'.join(sep) + ')(\d+)\..*$'))
matchers.append(some_other_regex_for_other_cases)
for matcher in matchers:
match = matcher.match(yourstring)
if match:
print match.groups()[-1]
Another, more generic way which is compatible with custom functions:
import re
matchers = []
simple_sep = ['S0001', '_0_']
simple_re = re.compile('^.*(' + '|'.join(sep) + ')(\d+)\..*$')
def simple_matcher(s):
m = simple_re.match(s)
if m:
return m.groups()[-1]
def other_matcher(s):
if s[3:].isdigit():
return s[3:]
matchers.append(simple_matcher)
matchers.append(other_matcher)
for matcher in matchers:
match = matcher('yourstring')
if match:
print int(match)