Concat string if condition, else do nothing - python

I want to concat few strings together, and add the last one only if a boolean condition is True.
Like this (a, b and c are strings):
something = a + b + (c if <condition>)
But Python does not like it. Is there a nice way to do it without the else option?
Thanks! :)

Try something below without using else. It works by indexing empty string when condition False (0) and indexing string c when condition True (1)
something = a + b + ['', c][condition]
I am not sure why you want to avoid using else, otherwise, the code below seems more readable:
something = a + b + (c if condition else '')

This should work for simple scenarios -
something = ''.join([a, b, c if condition else ''])

It is possible, but it's not very Pythonic:
something = a + b + c * condition
This will work because condition * False will return '', while condition * True will return original condition. However, You must be careful here, condition could also be 0 or 1, but any higher number or any literal will break the code.

Is there a nice way to do it without the else option?
Well, yes:
something = ''.join([a, b])
if condition:
something = ''.join([something, c])
But I don't know whether you mean literally without else, or without the whole if statement.

a_list = ['apple', 'banana,orange', 'strawberry']
b_list = []
for i in a_list:
for j in i.split(','):
b_list.append(j)
print(b_list)

Related

How to use rsplit with None vaules in Python?

At my Python application, I want to get a specific value from a list:
rating_unit_value = clean_result['format']['tags'].get('itunextc', None).rsplit('|', 3)[0]
The Problem here is that if 'itunextc' does not exist, it should return None instead, where rsplit can't work with a None value. So, how can I apply the rsplit only if 'itunextc' exists? Of course this can be done with an if else statement or try except, but is this really the only way to go ?
Something like this pseudocode would be cool:
rating_unit_value = clean_result['format']['tags'].get('itunextc'.rsplit('|', 3)[0], None)
Thanks in advance.
Using an assignment expression and a conditional expression:
rating_unit_value = val.rsplit('|', 3)[0] if (val := clean_result['format']['tags'].get('itunextc')) else None
Whether that is clearer (or generally "better") than an if-else or a try-except, is really in the eye of the beholder.
Simplified example:
>>> a = dict(b='1|1')
>>> e = val.split('|') if (val := a.get('c')) else None
>>> print(e)
None
>>> e = val.split('|') if (val := a.get('b')) else None
>>> e
['1', '1']

Why do these shorthands not work with each other?

I was wondering how to take advantage of shorthand notation of if-else and += in Python of this simple expression:
I tried to set brackets everywhere and changed += to *= which didn't change the situation of course.
This works as expected:
a, b = 0, True
for i in range(123):
if b == True:
a = a + 1
Still working as expected, trying shorthand of if-else led me to:
a, b = 0, True
for i in range(123):
a = a + 1 if b == True else a
Finally the attempt to write:
a, b = 0, True
for i in range(123):
a += 1 if b == True else a:
fails and surprisingly I get pretty quickly huge integers for a
Moreover I'd really like something more shorthanded, e.g.:
a, b = 0, True
for i in range(123):
a += 1 if b
The for-loop needs to stay as it is, since in my case there are other operations that affect b.
Since noone seems to be posting, why it goes like this, here is mine - lines:
a = a + 1 if b == True else a
a += 1 if b == True else a
are seen by python as:
a = (a + 1 if b == True else a)
a += (1 if b == True else a)
This is why you get large numbers fast in second version - you will add a to a, when b is False. If you want to keep the if, then go:
a += (1 if b else 0)
Also don't compare b to True (or False), go foif b`, as it's more pythonic (it will prevent some weird mistakes, when other code will start to interact with yours).
EDIT: go for #Tomerikoo answer for even shorter code, but keep in mind, that those waters can be muddy and not everyone knows / easily follows, that adding boolean to int treats first as 1 (or 0 if False).
To closest to your proal is probably:
a, b = 0, True
for i in range(123):
a += b
Since bool is a subtype of int, no conversion is necessary.
You can do:
for i in range(123):
if b:a+=1
You can also do:
for i in range(123):
a = a + 1*b
Because booleans are ints:
>>> isinstance(True, int)
True
>>> True == 1
True
just note that
a += x if condition else y
will resolve to a += x if the condition is True; otherwise it will be a += y. this is why your numbers get big...
apart from that i suggest you use what U10-Forward's answer suggests.

Simplifying an 'if' statement with bool()

I have some code that causes Pylint to complain:
The if statement can be replaced with 'var = bool(test)' (simplifiable-if-statement)`
The code (with obfuscated variable names) is below.
A = True
B = 1
C = [1]
D = False
E = False
if A and B in C:
D = True
else:
E = True
print(D, E)
How can this be simplified so that Pylint does not throw any errors?
I don't quite understand how bool() can be used for this. I know it converts any value to a Boolean value, but I don't know how it can be applied here.
That logic can be expressed as:
D = A and B in C
E = not D
Try this:
D = bool(A and B in C)
E = not bool(A and B in C)
I was initially a bit confused by the accepted answer and then realized my problem was not with the accepted answer itself (which is fully correct indeed) but with the specificity of the question. I needed a more generic / simple use case and so I will try to provide one, hoping it will be of help for someone.
The simplifiable-if-statement Pylint refactor basically happens when we use an if-else statement to assign a value to a boolean variable, which could have otherwise been assigned directly, without using the if-else statement at all.
A generic example could be:
if <condition>:
variable = True
else:
variable = False
which can (and should) be simplified as:
variable = <condition>
where <condition> is a boolean expression.
A concrete example:
if a > 5:
b = True
else:
b = False
should be rewritten as
b = a > 5
Getting back to the original question, in this case the condition is A and B in C and, as pointed out by other contributors, the redundant snippet:
D = False
E = False
if A and B in C:
D = True
else:
E = True
should be simplified as
D = A and B in C
E = not D

How to test if a string has capital letters

In Scala I could test if a string has a capital letter like this:
val nameHasUpperCase = name.exists(_.isUpper)
The most comprehensive form in Python I can think of is:
a ='asdFggg'
functools.reduce(lambda x, y: x or y, [c.isupper() for c in a])
->True
Somewhat clumsy. Is there a better way to do this?
The closest to the Scala statement is probably an any(..) statement here:
any(x.isupper() for x in a)
This will work in using a generator: from the moment such element is found, any(..) will stop and return True.
This produces:
>>> a ='asdFggg'
>>> any(x.isupper() for x in a)
True
Or another one with map(..):
any(map(str.isupper,a))
Another way of doing this would be comparing the original string to it being completely lower case:
>>> a ='asdFggg'
>>> a == a.lower()
False
And if you want this to return true, then use != instead of ==
There is also
nameHasUpperCase = bool(re.search(r'[A-Z]', name))

Checking if elements exist in list using python

I am new to python and was wondering if someone could help me out with this. I am trying to see if the elements in b are in a. This is my attempt. Currently I am not getting any output. Any help would be appreciated, thank you!
a = [1]
b = [1,2,3,4,5,6,7]
for each in b:
if each not in a == True:
print(each + "is not in a")
You are testing two different things, and the outcome is False; Python is chaining the operators, effectively testing if (each is in a) and (a == True):
>>> 'a' in ['a'] == True
False
>>> ('a' in ['a']) and (['a'] == True)
False
>>> ('a' in ['a']) == True
True
You never need to test for True on an if statement anyway:
if each not in a:
is enough.
You should be able to just say:
if each not in a:
print ("%d is not in a" % each)
Your actual expression is using operator chaining:
if a > b > c:
parses as:
if (a > b) and (b > c):
in python. which means your expression is actually being parsed as:
if (each not in a) and (a == True):
but a == True will always return False, so that if block will never execute.
a = [1,2,3]
b = [1,2,3,4,5,6,7]
c = [7,8,9]
print set(a) <= set(b) #all elements of a are in b
print set(c) <= set(b) #all elements of c are in b
It is better to see the difference between B and A
set(b).difference(set(a))
You don't need ==True. Just:
if each not in a:
This is really easy using sets:
a = [1]
b = [1, 2]
only_in_b = set(b) - set(a)
# set([2])
Another way:
for bb in b:
try:
a.index(bb)
except:
print 'value is not in the list: ' + str(bb)
I would like to add that if the two lists are large. This is not the best way to do it. Your algorithm is O(n^2). The best way is to traverse a, adding the elements as keys to a dictionary. Afterwards, traverse the second list, checking if the elements are already in the dictionary, this instead is an O(n) algorithm.

Categories

Resources