How to replace a numerical value in a Python list - python

So I got this list of lists:
lst = [[0,1],2,[3]]
and I got a list of tuples:
lst_2 = [("x1","y1"),("x2","y2"), ("x3","y3"), ("x4","y4")]
I want to replace values inside lst with the index 0 value of each of the tuples in lst_2, and the tuple taken depends on the numerical value in lst. So it becomes:
lst = [["x1","x2"], "x3", ["x4"]]
Please don't roast me thanks so much

Try this:
lst = [[0,1],2,[3]]
lst_2 = [("x1","y1"),("x2","y2"), ("x3","y3"), ("x4","y4")]
res = []
for l in lst:
if isinstance(l, list):
res += [[lst_2[i][0] for i in l]]
else:
res += [lst_2[l][0]]
print(res)
Or with List Comprehensions:
res = [[lst_2[i][0] for i in l] if isinstance(l, list) else lst_2[l][0] for l in lst]
[['x1', 'x2'], 'x3', ['x4']]

You could use recursion to allow lst to have deeper levels of nesting:
def produce(template, data):
return [
produce(nested, data) for nested in template
] if isinstance(template, list) else data[template][0]
# Example
lst = [[0,[1]],2,[3]]
lst_2 = [("x1","y1"),("x2","y2"), ("x3","y3"), ("x4","y4")]
result = produce(lst, lst_2)

Related

adding empty string while joining the 2 lists - Python

I have 2 lists
mainlist=[['RD-12',12,'a'],['RD-13',45,'c'],['RD-15',50,'e']] and
sublist=[['RD-12',67],['RD-15',65]]
if i join both the list based on 1st element condition by using below code
def combinelist(mainlist,sublist):
dict1 = { e[0]:e[1:] for e in mainlist }
for e in sublist:
try:
dict1[e[0]].extend(e[1:])
except:
pass
result = [ [k] + v for k, v in dict1.items() ]
return result
Its results in like below
[['RD-12',12,'a',67],['RD-13',45,'c',],['RD-15',50,'e',65]]
as their is no element in for 'RD-13' in sublist, i want to empty string on that.
The final output should be
[['RD-12',12,'a',67],['RD-13',45,'c'," "],['RD-15',50,'e',65]]
Please help me.
Your problem can be solved using a while loop to adjust the length of your sublists until it matches the length of the longest sublist by appending the wanted string.
for list in result:
while len(list) < max(len(l) for l in result):
list.append(" ")
You could just go through the result list and check where the total number of your elements is 2 instead of 3.
for list in lists:
if len(list) == 2:
list.append(" ")
UPDATE:
If there are more items in the sublist, just subtract the lists containing the 'keys' of your lists, and then add the desired string.
def combinelist(mainlist,sublist):
dict1 = { e[0]:e[1:] for e in mainlist }
list2 = [e[0] for e in sublist]
for e in sublist:
try:
dict1[e[0]].extend(e[1:])
except:
pass
for e in dict1.keys() - list2:
dict1[e].append(" ")
result = [[k] + v for k, v in dict1.items()]
return result
You can try something like this:
mainlist=[['RD-12',12],['RD-13',45],['RD-15',50]]
sublist=[['RD-12',67],['RD-15',65]]
empty_val = ''
# Lists to dictionaries
maindict = dict(mainlist)
subdict = dict(sublist)
result = []
# go through all keys
for k in list(set(list(maindict.keys()) + list(subdict.keys()))):
# pick the value from each key or a default alternative
result.append([k, maindict.pop(k, empty_val), subdict.pop(k, empty_val)])
# sort by the key
result = sorted(result, key=lambda x: x[0])
You can set up your empty value to whatever you need.
UPDATE
Following the new conditions, it would look like this:
mainlist=[['RD-12',12,'a'], ['RD-13',45,'c'], ['RD-15',50,'e']]
sublist=[['RD-12',67], ['RD-15',65]]
maindict = {a:[b, c] for a, b, c in mainlist}
subdict = dict(sublist)
result = []
for k in list(set(list(maindict.keys()) + list(subdict.keys()))):
result.append([k, ])
result[-1].extend(maindict.pop(k, ' '))
result[-1].append(subdict.pop(k, ' '))
sorted(result, key=lambda x: x[0])
Another option is to convert the sublist to a dict, so items are easily and rapidly accessible.
sublist_dict = dict(sublist)
So you can do (it modifies the mainlist):
for i, e in enumerate(mainlist):
data: mainlist[i].append(sublist_dict.get(e[0], ""))
#=> [['RD-12', 12, 'a', 67], ['RD-13', 45, 'c', ''], ['RD-15', 50, 'e', 65]]
Or a one liner list comprehension (it produces a new list):
[ e + [sublist_dict.get(e[0], "")] for e in mainlist ]
If you want to skip the missing element:
for i, e in enumerate(mainlist):
data = sublist_dict.get(e[0])
if data: mainlist[i].append(data)
print(mainlist)
#=> [['RD-12', 12, 'a', 67], ['RD-13', 45, 'c'], ['RD-15', 50, 'e', 65]]

Python: Adding integer elements of a nested list to a list

So, I have two lists whose integer elements need to be added.
nested_lst_1 = [[6],[7],[8,9]]
lst = [1,2,3]
I need to add them such that every element in the nested list, will be added to its corresponding integer in 'lst' to obtain another nested list.
nested_list_2 = [[6 + 1],[7 + 2],[8 + 3,9 + 3]]
or
nested_list_2 = [[7],[9],[11,12]]
Then, I need to use the integers from nested_list_1 and nested_list_2 as indices to extract a substring from a string.
nested_list_1 = [[6],[7],[8,9]] *obtained above*
nested_list_2 = [[7],[9],[11,12]] *obtained above*
string = 'AGTCATCGTACGATCATCGAAGCTAGCAGCATGAC'
string[6:7] = 'CG'
string[7:9] = 'GTA'
string[8:11] = 'TACG'
string[9:12] = 'ACGA'
Then, I need to create a nested list of the substrings obtained:
nested_list_substrings = [['CG'],['GTA'],['TACG','ACGA']]
Finally, I need to use these substrings as key values in a dictionary which also possesses keys of type string.
keys = ['GG', 'GTT', 'TCGG']
nested_list_substrings = [['CG'],['GTA'],['TACG','ACGA']]
DNA_mutDNA = {'GG':['CG'], 'GTT':['GTA'], 'TCGG':['TACG','ACGA']}
I understand that this is a multi-step problem, but if you could assist in any way, I really appreciate it.
Assuming you don't need the intermediate variables, you can do all this with a dictionary comprehension:
a = [[6],[7],[8,9]]
b = [1,2,3]
keys = ['GG', 'GTT', 'TCGG']
s = 'AGTCATCGTACGATCATCGAAGCTAGCAGCATGAC'
DNA_mutDNA = {k: [s[start:start+length+1] for start in starts]
for k, starts, length in zip(keys, a, b)}
You can produce the substring list directly with a nested list comprehension, nested_lst_2 isn't necessary.
nested_lst_1 = [[6],[7],[8,9]]
lst = [1,2,3]
string = 'AGTCATCGTACGATCATCGAAGCTAGCAGCATGAC'
keys = ['GG', 'GTT', 'TCGG']
substrings = [[string[v:i+v+1] for v in u] for i, u in zip(lst, nested_lst_1)]
print(substrings)
DNA_mutDNA = dict(zip(keys, substrings))
print(DNA_mutDNA)
output
[['CG'], ['GTA'], ['TACG', 'ACGA']]
{'GG': ['CG'], 'GTT': ['GTA'], 'TCGG': ['TACG', 'ACGA']}
In[2]: nested_lst_1 = [[6],[7],[8,9]]
...: lst = [1,2,3]
...: string = 'AGTCATCGTACGATCATCGAAGCTAGCAGCATGAC'
...: keys = ['GG', 'GTT', 'TCGG']
In[3]: nested_lst_2 = [[elem + b for elem in a] for a, b in zip(nested_lst_1, lst)]
In[4]: nested_list_substrings = []
...: for a, b in zip(nested_lst_1, nested_lst_2):
...: nested_list_substrings.append([string[c:d + 1] for c, d in zip(a, b)])
...:
In[5]: {k: v for k, v in zip(keys, nested_list_substrings)}
Out[5]: {'GG': ['CG'], 'GTT': ['GTA'], 'TCGG': ['TACG', 'ACGA']}
Surely not the most readable way to do it, here is a bit of functional style fun:
nested_lst_1 = [[6], [7], [8,9]]
lst = [1, 2, 3]
nested_lst_2 = list(map(
list,
map(map, map(lambda n: (lambda x: n+x), lst), nested_lst_1)))
nested_lst_2
Result looks as expected:
[[7], [9], [11, 12]]
Then:
from itertools import starmap
from operator import itemgetter
make_slices = lambda l1, l2: starmap(slice, zip(l1, map(lambda n: n+1, l2)))
string = 'AGTCATCGTACGATCATCGAAGCTAGCAGCATGAC'
get_slice = lambda s: itemgetter(s)(string)
nested_list_substrings = list(map(
lambda slices: list(map(get_slice, slices)),
starmap(make_slices, zip(nested_lst_1, nested_lst_2))))
nested_list_substrings
Result:
[['CG'], ['GTA'], ['TACG', 'ACGA']]
And finally:
keys = ['GG', 'GTT', 'TCGG']
DNA_mutDNA = dict(zip(keys, nested_list_substrings))
DNA_mutDNA
Final result:
{'GG': ['CG'], 'GTT': ['GTA'], 'TCGG': ['TACG', 'ACGA']}

Sum lists with different lengths in python

I have 3 lists with different lengths. They are made like this:
final_list = [[1230, 0], [1231,0],[1232,0], [1233, 0], [1234, 0]]
list2 = [[1232, 20], [1233, 30]]
list3 = [[1230, 10], [1231,20],[1232,40]]
What I want to obtain the final_list like this:
final_list = [[1230, 10], [1231,20],[1232,60], [1233, 30], [1234, 0]]
(If, considering each element of list2 and list3, its first value is equal to one of the first elements of the final list, then the corresponding element of the final list has to have the second value equal to the sum of the elements found.)
Not a clean solution, but easy to grasp and might save your day.
f = {}
dcts = map(lambda l: dict([l]), list2+list3)
for dct in dcts:
for k in dct.iterkeys():
f[k] = w.get(k, 0) + d[k]
final_list = map(list, f.items())
however, if you are familiar with itertools
import groupby from itertools
merged = list2+list3
final_list = []
for key, group in groupby(merged, key = lambda e: e[0]):
final_list.append([key, sum(j for i, j in group)])
or a oneliner
[[k, sum(j for i, j in g)] for k, g in groupby(list3+list2, key = lambda e: e[0])]
I created a temp_list and append all three lists to it.
create a dictionary dic and loop through temp_list to sum up each tuple base on the key.
then I turn the dic back into a list and sort it.
I admit this is not the most efficient way to do this. but it is a solution.
temp_list = []
temp_list.append(final_list)
temp_list.append(list2)
temp_list.append(list3)
dic = {}
for lst in temp_list:
for tp in lst:
if tp[0] in dic:
dic[tp[0]] = dic[tp[0]] + tp[1]
else:
dic[tp[0]] = tp[1]
result = []
for key, value in dic.iteritems():
temp = [key,value]
result.append(temp)
result.sort()
result:
[(1230, 10), (1231, 20), (1232, 60), (1233, 30), (1234, 0)]

Slice a list into a nested list based on special characters using Python

I have a list of strings like this:
lst = ['23532','user_name=app','content=123',
'###########################',
'54546','user_name=bee','content=998 hello','source=fb',
'###########################',
'12/22/2015']
I want a similar method like string.split('#') that can give me output like this:
[['23532','user_name=app','content='123'],
['54546','user_name=bee',content='998 hello','source=fb'],
['12/22/2015']]
but I know list has not split attribute. I cannot use ''.join(lst) either because this list comes from part of a txt file I read in and my txt.file was too big, so it will throw an memory error to me.
I don't think there's a one-liner for this, but you can easily write a generator to do what you want:
def sublists(lst):
x = []
for item in lst:
if item == '###########################': # or whatever condition you like
if x:
yield x
x = []
else:
x.append(item)
if x:
yield x
new_list = list(sublists(old_list))
If you can't use .join(), you can loop through the list and save the index of any string that contains # then loop again to slice the list:
lst = ['23532', 'user_name=app', 'content=123', '###########################' ,'54546','user_name=bee','content=998 hello','source=fb','###########################','12/22/2015']
idx = []
new_lst = []
for i,val in enumerate(lst):
if '#' in val:
idx.append(i)
j = 0
for x in idx:
new_lst.append(lst[j:x])
j = x+1
new_lst.append(lst[j:])
print new_lst
output:
[['23532', 'user_name=app', 'content=123'], ['54546', 'user_name=bee', 'content=998 hello', 'source=fb'], ['12/22/2015']]
sep = '###########################'
def split_list(_list):
global sep
lists = list()
sub_list = list()
for x in _list:
if x == sep:
lists.append(sub_list)
sub_list = list()
else:
sub_list.append(x)
lists.append(sub_list)
return lists
l = ['23532','user_name=app','content=123',
'###########################',
'54546','user_name=bee','content=998 hello','source=fb',
'###########################',
'12/22/2015']
pprint(split_list(l))
Output:
[['23532', 'user_name=app', 'content=123'],
['54546', 'user_name=bee', 'content=998 hello', 'source=fb'],
['12/22/2015']]
You can achieve this by itertools.groupby
from itertools import groupby
lst = ['23532','user_name=app','content=123',
'###########################','54546','user_name=bee','content=998 hello','source=fb',
'###########################','12/22/2015']
[list(g) for k, g in groupby(lst, lambda x: x == '###########################') if not k ]
Output
[['23532', 'user_name=app', 'content=123'],
['54546', 'user_name=bee', 'content=998 hello', 'source=fb'],
['12/22/2015']]

Converting this loop to a list comprehension

I would like to generate a list of unique Ids by only keeping the list that has the minimum value in element 2.
For example, given the list:
list1 = [['Id1', 1, 40],['Id1', 2, 30],['Id2', 10,40]]`
Expected output:
[['Id1', 1, 40],['Id2', 10,40]]
Here's my working example, but it's pretty clunky. I think it could probably be done with a single list comprehension.
list1 = [['Id1', 1, 40],['Id1', 2, 30],['Id2', 10,40]]
unique_list = list(set([x[0] for x in list1]))
unique_list = [[x] for x in unique_list]
for x in unique_list:
id = x[0]
min_val = min([y[1:] for y in list1 if y[0] == id])
x.extend(min_val )
print unique_list
You can use itertools.groupby to group by the first element in the sublists, the you can get the min with a key argument to sort by the remaining elements in the sublist.
>>> from itertools import groupby
[min(list(g), key = lambda i: i[1:]) for k, g in groupby(list1, lambda i: i[0])]
[['Id1', 1, 40], ['Id2', 10, 40]]
A very naive approach but easily understandable.
list1 = [['Id1', 1, 40],['Id1', 2, 30],['Id2', 10,40]]
unique_list = []
for list_element in list1:
appendable = True
for temp_list in unique_list:
if list_element[0] == temp_list[0]:
if temp_list[1] < list_element[1]:
appendable = False
else:
unique_list.remove(temp_list)
if appendable == True:
unique_list.append(list_element)
unique_list.sort()
print unique_list

Categories