Python: Add Same Prefix to All Elements in List - python

Let's say I have the following Python List:
['7831-0', nan, '3165-0', '7831-0', '7831-1']
I want to add the same prefix ('ADD_' to each element in the above list. I also want to remove the nan from my list. My desired output list is as follows:
list = ['ADD_7831-0', 'ADD_3165-0', 'ADD_7831-0', 'ADD_7831-1']
I tried the following code:
prefix_ADD = 'ADD_'
new_list = [prefix_ADD + x for x in list]
But I get the following error:
TypeError: must be str, not float

[prefix_ADD + x for x in list if not str(x) == "nan"]
Is one way you could filter out nan

your_list = ['7831-0', float('nan'), '3165-0', '7831-0', '7831-1']
print(your_list) # ['7831-0', nan, '3165-0', '7831-0', '7831-1']
prefix_ADD = 'ADD_'
new_list = [prefix_ADD + x for x in your_list if isinstance(x, str)]
print(new_list) # ['ADD_7831-0', 'ADD_3165-0', 'ADD_7831-0', 'ADD_7831-1']

Maybe a less elegant solution but how about this:
new_list=[]
old_list = ['7831-0', nan, '3165-0', '7831-0', '7831-1']
prefix_ADD = 'ADD_'
for x in old_list:
if x != nan:
new_list.append(prefix_ADD + x)
print(new_list)
# ['ADD_7831-0', 'ADD_3165-0', 'ADD_7831-0', 'ADD_7831-1']

Related

How to change the nth character of every string in a list in Python

Let's say I have the following list of strings:
list = ['ABC.010120.01', 'ABC.010220.02', 'ABC.010220.03']
I want to change the 11th character of each string, meaning the 2nd '.', to a '-'.
I've tried:
list = [n[:10] + '-' + n[11:] for n in list]
However this gives me the error:
TypeError: 'float' object is not subscriptable
The problem is that you have a float somewhere in your list. You could use a for loop using enumerate and str to solve it:
lst = ['ABC.010120.01', 'ABC.010220.02', 'ABC.010220.03']
for index, item in enumerate(lst):
item = str(item)
lst[index] = item[0:10] + "-" + item[11:]
Or, as a list comprehension:
new_lst = [item[0:10] + "-" + item[11:]
for x in lst
for item in [str(x)]]
Also, avoid calling your variables like builtin-objects (list, dict and the like).
>>> a = ['ABC.010120.01', 'ABC.010220.02', 'ABC.010220.03']
>>> a = [n[:10] + '-' + n[11:] for n in a]
>>> a
['ABC.010120-01', 'ABC.010220-02', 'ABC.010220-03']
Note that list, as str, set and some others are word reserved for python3.
What you're doing it's like change the base of an int, for example.
The issue is that there are nan float values in the list. I found that following this solution linked here worked to remove the nan's from my list as so:
lst = ['ABC.010120.01', 'ABC.010220.02', 'ABC.010220.03', nan]
lst = [x for x in lst if x == x]
Executing that beforehand allows this line to function without error:
lst = [n[:10] + '-' + n[11:] for n in last]

Delete end of element from a list if the element ends with an element from another list

I have the following two lists. If my_list ends with an extension from extensions, then it should be removed. I can't seem to find a solution that doesn't require too many lines of code.
Input:
my_list = ['abc_sum_def_sum', 'abc_sum_def_mean', 'abc_sum', 'abc_abc']
extensions = ['_sum', '_mean']
Output:
new_list = ['abc_sum_def', 'abc_sum_def', 'abc', 'abc_abc']
One-liner list comprehension:
new_list = [min(e[:(-len(ext) if e.endswith(ext) else len(e))] for ext in extensions) for e in my_list]
Result:
['abc_sum_def', 'abc_sum_def', 'abc', 'abc_abc']
Explanation:
What this does is basically loops over my_list, checks if its element e has either of the two extensions items at its end. If it does, it trims that extensions piece down. If it doesn't, leaves that element of my_list untouched. It basically first does this (without the min applied):
[[e[:(-len(ext) if e.endswith(ext) else len(e))] for ext in extensions] for e in my_list]
which produces:
[['abc_sum_def', 'abc_sum_def_sum'],
['abc_sum_def_mean', 'abc_sum_def'],
['abc', 'abc_sum'],
['abc_abc', 'abc_abc']]
and then applies min to collect the smaller item of each pair. That min corresponds to either the trimmed-down version of each element, or the untouched element itself.
To have a better pythonic approach, You can convert it into a list comprehension:
my_list = ['abc_sum_def_sum','abc_sum_def_mean','abc_sum','abc_abc']
extensions = ['_sum','_mean']
new_list =[]
for x in my_list:
for elem in extensions:
if x.endswith(elem):
y = x[:-len(elem)]
new_list.append(y)
This is one approach using Regex.
Ex:
import re
my_list = ['abc_sum_def_sum','abc_sum_def_mean','abc_sum','abc_abc']
extensions = ['_sum','_mean']
pattern = re.compile(r"(" + "|".join(extensions) + r")$")
print([pattern.sub("", i) for i in my_list])
Output:
['abc_sum_def', 'abc_sum_def', 'abc', 'abc_abc']
my_list = ['abc_sum_def_sum','abc_sum_def_mean','abc_sum','abc_abc']
extensions = ['_sum','_mean']
new_list =[]
for x in my_list:
if x.endswith(extensions[0]) or x.endswith(extensions[1]):
if x.endswith(extensions[0]):
y = x[:-len(extensions[0])]
new_list.append(y)
else:
y = x[:-len(extensions[1])]
new_list.append(y)
else:
new_list.append(x)
print(new_list)
output:
['abc_sum_def', 'abc_sum_def', 'abc', 'abc_abc']
A solution using lambdas:
my_list = ['abc_sum_def_sum','abc_sum_def_mean','abc_sum','abc_abc']
extensions = ['_sum','_mean']
def ext_cleaner(extensions, str_arg):
ext_found = [ext for ext in extensions if str_arg.endswith(ext)]
ret = str_arg[:-len(ext_found[0])] if ext_found else str_arg
return ret
list(map(lambda x: ext_cleaner(extensions, x), my_list))

Delete first two characters of elements in a list of lists

Let's say I have the following list of lists:
final_list = [[1,'pppizza',3,4],[1,'mmmonkey',9,10],[1,'dddoublerainbow',8,2]]
Now I need to remove the first 2 characters of the second element of every list, so the result will be:
final_list = [[1,'pizza',3,4],[1,'monkey',9,10],[1,'doublerainbow',8,2]]
No need to rebuild the entire list from scratch just to do it in a one-line comprehension while unnecessarily iterating the inner lists. Just modify the elements that need modifying:
for lst in final_list:
lst[1] = lst[1][2:]
use double list comprehensions:
final_list = [[x if hasattr(x, '__len__') and i == 1 else x[2:] for i, x in enumerate(y)] for y in my_list]
this will trim the first 2 elements of the second element, even if the element is not a string
If you want it for strings only then the statement becomes:
final_list = [[x if type(x) == str and i == 1 else x[2:] for i, x in enumerate(y)] for y in my_list]
final_list = [[x[2:] if i==1 else x for i, x in enumerate(y)] for y in my_list]
Full answer:
final_list = []
for y in my_list:
l = []
for i, x in enumerate(my_list):
if i==1: #2nd element in the list
l.append(x[2:]) # Append a string starting from the 3rd letter to the end
else:
l.append(x) . # Just append the element at x
my_list.append(l) # Append the list l to my_list
print(my_list)

Prepend a string in Python

I'm trying to prepend zeros to each number in a list if it isn't a the necessary number of digits.
lst = ['1234','2345']
for x in lst:
while len(x) < 5:
x = '0' + x
print(lst)
Ideally this would print ['012345', '02345']
You can use zfill:
Pad a numeric string s on the left with zero digits until the given
width is reached
lst = ['1234','2345']
[s.zfill(5) for s in lst]
# ['01234', '02345']
Or use format method with padding and alignment:
["{:0>5}".format(s) for s in lst]
# ['01234', '02345']
You code doesn't do the job because strings in python are immutable, see this for more info Why doesn't calling a Python string method do anything unless you assign its output?
You could you enumerate in this case like this:
lst = ['1234','2345', "23456"]
for i, l in enumerate(lst):
if len(l) < 5:
lst[i] = '0' + l
print(lst)
['01234', '02345', '23456']
You could use a list comprehension like this:
>>> ['0' * (5-len(x)) + x for x in lst]
['01234', '02345']
Or a list + map try:
>>> list(map(lambda x: '0' * (5-len(x)) + x, lst))
['01234', '02345']
Ultimately, it was a combination of the answers that did the job.
lst = ['1234','2345']
newlst = []
for i in lst:
i = i.zfill(5)
newlst.append(i)
print(newlst)
I apologize if my example wasn't clear. Thank you to all who offered answers!
You can do this:
>>> lst = ['1234','2345']
>>> lst = ['0' * (5 - len(i)) + i for i in lst]
>>> print(lst)
['01234', '02345']

Selection elements of a list based on another 'True'/'False' list

I have two lists of the same length.
The first one contains strings. The second one - strings that can be either 'True' or 'False'.
If the nth element of the second list is 'True', I want to append the nth element of the first list to another list.
So if I have:
List1:
('sth1','sth2','sth3','sth4')
List2:
('True','False','True','False')
The outcome should be List3:
('sth1','sth3').
How can I intersect two list in that way?
Use zip:
result = [x for x, y in zip(xs, ys) if y == 'True']
Example:
xs = ('sth1','sth2','sth3','sth4')
ys = ('True','False','True','False')
result = [x for x, y in zip(xs, ys) if y == 'True']
result
['sth1', 'sth3']
Or use numpy:
import numpy as np
filtered = np.array(List1)[np.array(List2)]
Btw this only works if the elements inside List2 are True/False, not if they are "True"/"False".
If you didn't know about zip :
l1 = ('sth1','sth2','sth3','sth4')
l2 = ('True','False','True','False')
l = [x for i,x in enumerate(l1) if l2[i]=='True']
print l
#=> ['sth1', 'sth3']
It would be shorter with a tuple of booleans :
l1 = ('sth1','sth2','sth3','sth4')
l2 = (True,False,True,False)
l = [x for i,x in enumerate(l1) if l2[i]]
print l
Simplest way is to use itertools.compress method as follows.
import itertools
list1 = ('sth1','sth2','sth3','sth4')
list2 = ('True','False','True','False')
list2 = map(lambda x: x == 'True', list2)
result = list(itertools.compress(list1, list2))
compress method returns an iterator, so you that is why you need to wrap the iterator object in list
I hope it helps.

Categories