During string concatenation, how to add delimiter only if variable is set? - python

How to add the delimiter only if that variable has a value, in the below code, I am trying to avoid 2 underscores like: foo_bar__baz, a,b,d will be always set, only c is optional, is there a more pythonic way?
>>> a_must='foo'
>>> b_must='bar'
>>> c_optional=''
>>> d_must='baz'
>>>
>>> f'{a_must}_{b_must}_{c_optional}_{d_must}' if c_optional else
f'{a_must}_{b_must}_{d_must}'
'foo_bar_baz'
Its in python3.6

You can write the conditional inside the f-string itself:
f'{a_must}_{b_must}_{c_optional+"_" if c_optional else ""}{d_must}'
Output:
'foo_bar_baz'

To be a little more flexible, something like this would work:
variables = [a_must, b_must, c_optional, d_must]
'_'.join([x for x in variables if x])

You can build a list of tokens and use str.join to join the list into a string with _ as the delimiter:
tokens = [a_must, b_must]
if c_optional:
tokens.append(c_optional)
tokens.append(d_must)
print('_'.join(tokens))

Your solution works fine, it just needed a little formatting. I added the print statement for testing.
a_must='foo'
b_must='bar'
c_optional=''
d_must='baz'
if c_optional:
result = f'{a_must}_{b_must}_{c_optional}_{d_must}'
else:
result = f'{a_must}_{b_must}_{d_must}'
print(result)

Related

How to append a list withoud adding the quote

I have this code:
def add_peer_function():
all_devices=[]
all_devices.append("cisco,linux")
print(all_devices)
add_peer_function()
Which results in :
['cisco,linux']
My question is how can append the list without qota. So a result like this:
[cisco,router]
Well, I know two possible ways, but the first one is faster:
1:
def add_peer_function():
all_devices=[item for item in "cisco,linux".split(',')] # or `all_devices = ["cisco", "linux"]`
print(', '.join(all_devices)) # A prettier way to print list Thanks to Philo
add_peer_function()
2:
def add_peer_function():
all_devices=[]
for item in "cisco,linux".split(','): # or `all_devices = ["cisco", "linux"]`
all_devices.append(item)
print(', '.join(all_devices)) # A prettier way to print list Thanks to Philo
add_peer_function()
Python str.split documentation.
Python str.join documentation.
Python list comprehension documentation.
Python prints objects, by default, with its convention: strings are between quotes.
If you want to get another format, you can write your own formatter.
For lists of strings, a common pattern in Python is:
my_list = ['one', 'two', 'three']
print(', '.join(my_list))
Replace ', ' by another separator, eventually.
Finally, note that "cisco,linux" is just a string with a coma, which is different from a list of strings: ["cisco", "linux"].
Of course, if you append the string 'cisco,linux' to a list, you get ['cisco,linux'] which is the string representation of this list in Python.
What you what is to split the string.
Try:
>>> 'cisco,linux'.split(',')
['cisco', 'linux']
append accepts only one argument. so, your_list.append(something) will add something to your_list. you can however do sth like below.
your_list += [el for el in "cisco,linux".split(",")]

How to remove all the values in a string except for the chosen ones [duplicate]

This question already has answers here:
Keeping only certain characters in a string using Python?
(3 answers)
Closed 5 years ago.
So my code is
value = "123456"
I want to remove everything except for 2 and 5.
the output will be 25
the program should work even the value is changed for example
value = "463312"
the output will be 2
I tried to use remove() and replace() function. But it didn't work.
Doing it on python 3.6.2
Instead of trying to remove every unwanted character, you will be better off to build a whitelist of the characters you want to keep in the result:
>>> value = '123456'
>>> whitelist = set('25')
>>> ''.join([c for c in value if c in whitelist])
'25'
Here is another option where the loop is implicit. We build a mapping to use with str.translate where every character maps to '', unless specified otherwise:
>>> from collections import defaultdict
>>> d = defaultdict(str, str.maketrans('25', '25'))
>>> '123456'.translate(d)
'25'
In case you are looking for regex solution then you can use re.sub to replace all the characters other than 25 with ''.
import re
x = "463312"
new = re.sub('[^25]+' ,'', x)
x = "463532312"
new = re.sub('[^25]+' ,'', x)
Output:
2, 522
If you are using Python 2, you can use filter like this:
In [60]: value = "123456"
In [61]: whitelist = set("25")
In [62]: filter(lambda x: x in whitelist, value)
Out[62]: '25'
If you are using Python 3, you would need to "".join() the result of the filter.
value="23456"
j=""
for k in value:
if k=='2' or k=='5':
j=j+k
print (j)
It is the woorking program of what you said, You can give any input to the value, it will always print 25.
value = "123456"
whitelist = '25'
''.join(set(whitelist) & set(value))
'25'
I tried to approach this differently using the Python built-in filter() method with lambda. See below:
a = "1225866125" # Should return "22525"
whitelist = '25'
# Use filter to remove all elements that does not match the condition
a = "".join(filter(lambda c: c in whitelist, a))
Hope this helped!
(Edited to shorten the answer, credit #Akavall + again #salparadise)

python parsing a string

I have a list with strings.
list_of_strings
They look like that:
'/folder1/folder2/folder3/folder4/folder5/exp-*/exp-*/otherfolder/file'
I want to part this string into:
/folder1/folder2/folder3/folder4/folder5/exp-* and put this into a new list.
I thought to do something like that, but I am lacking the right snippet to do what I want:
list_of_stringparts = []
for string in sorted(list_of_strings):
part= string.split('/')[7] # or whatever returns the first part of my string
list_of_stringparts.append(part)
has anyone an idea? Do I need a regex?
You are using array subscription which extracts one (eigth) element. To get first seven elements, you need a slicing [N:M:S] like this:
>>> l = '/folder1/folder2/folder3/folder4/folder5/exp-*/exp-*/otherfolder/file'
>>> l.split('/')[:7]
['', 'folder1', 'folder2', 'folder3', 'folder4', 'folder5', 'exp-*']
In our case N is ommitted (by default 0) and S is step which is by default set to 1, so you'll get elements 0-7 from the result of split.
To construct your string back, use join():
>>> '/'.join(s)
'/folder1/folder2/folder3/folder4/folder5/exp-*'
I would do like this,
>>> s = '/folder1/folder2/folder3/folder4/folder5/exp-*/exp-*/otherfolder/file'
>>> s.split('/')[:7]
['', 'folder1', 'folder2', 'folder3', 'folder4', 'folder5', 'exp-*']
>>> '/'.join(s.split('/')[:7])
'/folder1/folder2/folder3/folder4/folder5/exp-*'
Using re.match
>>> s = '/folder1/folder2/folder3/folder4/folder5/exp-*/exp-*/otherfolder/file'
>>> re.match(r'.*?\*', s).group()
'/folder1/folder2/folder3/folder4/folder5/exp-*'
Your example suggests that you want to partition the strings at the first * character. This can be done with str.partition():
list_of_stringparts = []
list_of_strings = ['/folder1/folder2/folder3/folder4/folder5/exp-*/exp-*/otherfolder/file', '/folder1/exp-*/folder2/folder3/folder4/folder5/exp-*/exp-*/otherfolder/file', '/folder/blah/pow']
for s in sorted(list_of_strings):
head, sep, tail = s.partition('*')
list_of_stringparts.append(head + sep)
>>> list_of_stringparts
['/folder/blah/pow', '/folder1/exp-*', '/folder1/folder2/folder3/folder4/folder5/exp-*']
Or this equivalent list comprehension:
list_of_stringparts = [''.join(s.partition('*')[:2]) for s in sorted(list_of_strings)]
This will retain any string that does not contain a * - not sure from your question if that is desired.

Split a string in python

a="aaaa#b:c:"
>>> for i in a.split(":"):
... print i
... if ("#" in i): //i=aaaa#b
... print only b
In the if loop if i=aaaa#b how to get the value after the hash.should we use rsplit to get the value?
The following can replace your if statement.
for i in a.split(':'):
print i.partition('#')[2]
>>> a="aaaa#b:c:"
>>> a.split(":",2)[0].split("#")[-1]
'b'
a = "aaaa#b:c:"
print(a.split(":")[0].split("#")[1])
I'd suggest from: Python Docs
str.rsplit([sep[, maxsplit]])
Return a list of the words in the string, using sep as the delimiter
string. If maxsplit is given, at most maxsplit splits are done, the
rightmost ones. If sep is not specified or None, any whitespace string
is a separator. Except for splitting from the right, rsplit() behaves
like split() which is described in detail below.
so to answer your question yes.
EDIT:
It depends on how you wish to index your strings too, it looks like Rstring does it from the right, so if your data is always "rightmost" you could index by 0 (or 1, not sure how python indexes), every time, rather then having to do a size check of the returned array.
do you really need to use split? split create a list, so isn't so efficient...
what about something like this:
>>> a = "aaaa#b:c:"
>>> a[a.find('#') + 1]
'b'
or if you need particular occurence, use regex instead...
split would do the job nicely. Use rsplit only if you need to split from the last '#'.
a="aaaa#b:c:"
>>> for i in a.split(":"):
... print i
... b = i.split('#',1)
... if len(b)==2:
... print b[1]

How to make it shorter (Pythonic)?

I have to check a lot of worlds if they are in string... code looks like:
if "string_1" in var_string or "string_2" in var_string or "string_3" in var_string or "string_n" in var_string:
do_something()
how to make it more readable and more clear?
This is one way:
words = ['string_1', 'string_2', ...]
if any(word in var_string for word in words):
do_something()
Reference: any()
Update:
For completeness, if you want to execute the function only if all words are contained in the string, you can use all() instead of any().
Also note that this construct won't do any unnecessary computations as any will return if it encounters a true value and a generator expression is used to create the Boolean values. So you also have some kind of short-circuit evaluation that is normally used when evaluating Boolean expressions.
import re
if re.search("string_1|string_2|string_n", var_strings): print True
The beauty of python regex it that it returns either a regex object (that gives informations on what matched) or None, that can be used as a "false" value in a test.
With regex that would be:
import re
words = ['string_1', 'string_2', ...]
if re.search('|'.join([re.escape(w) for w in words]), var_string):
blahblah
Have you looked at filter?
filter( lambda x: x in var_string, ["myString", "nextString"])
which then can be combined with map to get this
map( doSomething(), filter(lambda x: x in var_string, ["myString", "nextString"] ) )
EDIT:
of course that doesn't do what you want. Go with the any solution. For some reason I thought you wanted it done every time instead of just once.
>>> import re
>>> string="word1testword2andword3last"
>>> c=re.compile("word1|word2|word3")
>>> c.search(string)
<_sre.SRE_Match object at 0xb7715d40>
>>> string="blahblah"
>>> c.search(string)
>>>
one more way to achieve this
check = lambda a: any(y for y in ['string_%s'%x for x in xrange(0,10)] if y in a)
print check('hello string_1')

Categories