compare two lists with zeros en larger numbers - python

I have to compare two lists of elements with the same length. (as an example [0,562,256,0,0,856] and [265,0,265,0,874,958]. Both list have an amount of zeroes and an amount of numbers above 249. I want to compare these lists. If at an index both lists have a number different from 0 the number should be saved in a list. The result should be two lists with the same length with only numbers above 249 (in the example [256,856] and [265,958]). Thanks for your help!

Use zip() to pair up the elements of each list:
listA = [0,562,256,0,0,856]
listB = [265,0,265,0,874,958]
combined = zip(listA, listB)
resultA = [a for a, b in combined if a and b]
resultB = [b for a, b in combined if a and b]
gives:
>>> resultA
[256, 856]
>>> resultB
[265, 958]
You could also first use filter() to remove all pairs where one or the other element is 0:
combined = filter(lambda (a, b): (a and b), zip(listA, listB))
resultA = [a for a, b in combined]
resultB = [b for a, b in combined]

maybe we will find a better way,but
list1 = [0,562,256,0,0,856]
list2 = [265,0,265,0,874,958]
rest1 = []
rest2 = []
result1 = []
result2 = []
for i in range(len(list1)):
if list1[i] and list2[i]:
rest1.append(list1[i])
rest2.append(list2[i])
for i in range(len(rest1)):
if rest1[i] >249 and rest2[i]>249:
result1.append(rest1[i])
result2.append(rest2[i])
print(result1,result1)

Related

Adding each item from one list to each item from another list to third list

Image the following lists:
A = [1,2,3,4]
B = ['A','B','C','D']
C = [10,11,12,13]
D = [100,200,300,400]
I should get the following results:
Z = ['1A10100', '2B11200', '3C12300', '4D13400']
I can do this using a lot of empty arrays, do it first using a for loop for A and B than use this new list and append C for each i, etc.
The question is, can this be done in a smarter way. In my real case the lists are 6?
You can use a simple list comprehension:
Z = [''.join(str(x) for x in l) for l in zip(A,B,C,D)]
output: ['1A10100', '2B11200', '3C12300', '4D13400']
If you already have a container for your lists:
lists = [A,B,C,D]
[''.join(str(x) for x in l) for l in zip(*lists)]
Using a list comprehension we can try:
A = [1,2,3,4]
B = ['A','B','C','D']
C = [10,11,12,13]
D = [100,200,300,400]
nums = list(range(0, len(A)))
Z = [str(A[i]) + B[i] + str(C[i]) + str(D[i]) for i in nums]
print(Z) # ['1A10100', '2B11200', '3C12300', '4D13400']
If the length of each lists are fixed and same length you can simply loop by indices, concatenate them, and then push altogether one-by-one into the result array.
A = [1,2,3,4]
B = ['A','B','C','D']
C = [10,11,12,13]
D = [100,200,300,400]
# Prepare the empty array
result = []
# Concat and insert one-by-one
for i in range(len(A)):
result.append('{}{}{}{}'.format(A[i], B[i], C[i], D[i]))
print(result)
Output:
['1A10100', '2B11200', '3C12300', '4D13400']
There are also another way to concatenate and insert to the result array besides the code above:
You can assign a temporary variable to concatenate before inserting:
for i in range(len(A)):
tmp = str(A[i]) + B[i] + str(C[i]) + str(D[i])
result.append(tmp)
Or you can just put the variables in the inner curly brackets in this way
for i in range(len(A)):
result.append(f'{A[i]}{B[i]}{C[i]}{D[i]}')

How to compare two lists in python without changing the order

I want to compare list a with list b and find the common elements but the result list should have the order of list a.
a = ['apple','ora','bab','ooo']
b = ['ooo','nnn','apple','ora']
c = set(a) & set(b)
print(c)
set(['ooo', 'apple', 'ora'])
The result which am expecting is ['apple','ora','ooo'] the order as in list a
a = ['apple','ora','bab','ooo']
b = ['ooo','nnn','apple','ora']
common = [x for x in a if x in b]
print(common)
# ['apple', 'ora', 'ooo']

Pythonic Nested for - loops in Python

I am working on this code where I have nested for loops. a_list and b_list are list of tuples, where each tuple is made up of two tensors [(tens1, tens2), ...]. I am trying to compute the similarity of every tens1 in a_list to every tens1 in b_list. Below is the code I have. And the nested loop appears to be a bottleneck. Is there a better way(pythonic) that I can re-write the loops?
a2b= defaultdict(dict)
b2a= defaultdict(dict)
ab_sim = []
for a, vec_a in a_list:
for b, vec_b in b_list:
# Ignore combination if the first element in both a and b are same
if a[0] == b[0]:
continue
# Calculate cosine similarity of combination
sim = self.calculate_similarity(vec_a, vec_b )
a2b[a][b] = sim
b2a[b][a] = sim
ab_sim.append(sim)
The calculate_similarity is just a method computing cosine similarity. a_list and b_list could be of any size. I have b2a and a2b because I need them for other computations.
You could use a dictionary comprehension:
a2b = {a: {b: self.calculate_similarity(vec_a, vec_b )
for (b, vec_b) in b_list if a[0] != b[0]} for (a, vec_a) in a_list}
I think the most natural way to store this information is in a Matrix
from random import random
import numpy as np
n=3
a=[ (n*np.random.rand(n)//1, n*np.random.rand(n)//1) for _ in range(3) ]
b=[ (n*np.random.rand(n)//1, n*np.random.rand(n)//1) for _ in range(3) ]
similarity = lambda x,y: np.dot(x, y)/(np.linalg.norm(x)*np.linalg.norm(y))
sim_matrix = [[ similarity(x,y) if x[0]!=y[0] else np.inf for y,_ in b ] for x,_ in a]
print(*sim_matrix, sep="\n")
Complete code.
You can also use product from itertools:
from itertools import product
result = {(a,b): self.calculate_similarity(vec_a, vec_b)
if a[0] != b[0] else 1
for ((a, vec_a) ,(b, vec_b)) in product(a_list, b_list)}
Note that you get one dictionary with tuples index, instead of two redundant dictionaries.
EDITED: to get those two dictionaries back, you can use dict comprehension:
a2b = {a: {_b:v for (_a,_b), v in result.items() if _a==a} for (a,b) in result.keys()}
b2a = {b: {_a:v for (_a,_b), v in result.items() if _b==b} for (a,b) in result.keys()}
to get the list of similarity values, you can use ab_sim = list(result.values())

How to pass the empty list when doing list comprehension

I have to create a list with all combination of three multiple lists:
a = ['1','2']
b = ['3','4']
c = ['5']
name = []
delimiter = '_'
name = [i + delimiter + j + delimiter + k for i in a for j in b if b for k in c]
print (name)
['1_3_5', '1_4_5', '2_3_5', '2_4_5']
My question is, on some occasions list c is empty.
c = []
print (name)
[]
Is there a way to prevent it returning as an empty list by altering the list comprehension, without removing "k in c"?
You can use an extendible method which does not rely on explicit nested for loops. For example, using itertools.product and filter:
from itertools import product
a = ['1','2']
b = ['3','4']
c = ['5']
res = ['_'.join(i) for i in product(*filter(None, (a, b, c)))]
# ['1_3_5', '1_4_5', '2_3_5', '2_4_5']
With empty c:
c = []
res = ['_'.join(i) for i in product(*filter(None, (a, b, c)))]
# ['1_3', '1_4', '2_3', '2_4']

How to check if elements of one list/dict present in another list/dict in python

here is a scenario, I am checking if elements of A are present in B. while this code works, it takes a lot of time when I read through million of lines. The efficient way would be to make each list in A and B as dictionary and look if they are present in each other. But I am not able to think of a simple way to do dictionary lookup. That is for each key-value pair in dict A, I want to check if that key-value pair is present in dictB
A = [['A',[1,2,3]],['D',[3,4]],['E',[6,7]]]
B= [['A',[1,2,3]],['E',[6,7]],['F',[8,9]]]
count = 0
for line in A:
if len(line[1]) > 1:
if line in B:
count = count + 1
print count
convert the lists to tuples
convert the list of tuples to a set
intersect the two sets
print the length of the intersection
Example:
A = [['A',[1,2,3]],['D',[3,4]],['E',[6,7]]]
B = [['A',[1,2,3]],['E',[6,7]],['F',[8,9]]]
A_set = set((a, tuple(b)) for a, b in A)
B_set = set((a, tuple(b)) for a, b in B)
print len(A_set & B_set)
You could always try with a list comprehension and work your way up using this as a basis:
a = [[1], [5], [7]]
b = [[5], [7], [0]]
r = [x for x in a if x in b]
Make A and B into dictionaries:
dA = dict(A)
dB = dict(B)
Then, just check that the keys and values match:
count = 0
for k,v in dA.iteritems():
if dB.get(k) == v:
count += 1
You will need to do some pre-processing on B, so it's elements are immutable.
def deep_tuple(x):
if type(x) in [type(()), type([])]:
return tuple(map(deep_tuple,x))
return x
A = ['A',[1,2,3]],['D',[3,4]],['E',[6,7]]
B = ['A',[1,2,3]],['E',[6,7]],['F',[8,9]]]
B = set(deep_tuple(B))
count = 0
for line in A:
if len(line[1]) > 1:
if line in B:
count = count + 1
print count
Make B into a set. Lookup in a set is O(1), as compared to O(|B|) otherwise. The overall complexity of this operation will be proportional to O(|A|).

Categories

Resources