Reputation: 1448
I have two lists of different lengths. Example---
E1 = [1.0,1.3,1.69,2.1970,2.8561,.....]
and
E2 = [1.00,1.04,1.08,1.1249,1.1699,.....]
(of course E2 has more number of elements than E1). Now I want to compare E1 list with E2 and find the value closest to each element in E1, like 1.3 in E1 is nearest to 1.1699 in E2 in this example. Similarly I want to do this for all other elements in E1... So that if I form a new list E3 out of E2, that will contain exactly similar number of elements as E1 and values closest to E1 elements. How can I do this ? Any help is appreciated..
Upvotes: 2
Views: 137
Reputation: 179392
Let me introduce you to a most marvelous Python module, bisect
.
import bisect
def find_nearest(refsort, pt):
loc = bisect.bisect_left(refsort, pt)
if loc >= len(refsort)-1:
# Value greater than all elements of refsort
return refsort[-1]
d1 = pt - refsort[i]
d2 = refsort[i+1] - pt
if d1 < d2:
return refsort[i]
else:
return refsort[i+1]
def replace_with_nearest(ptlist, reflist):
''' Replace every point in ptlist with the nearest value from reflist '''
refsort = sorted(reflist) # omit if you know reflist is sorted
return [find_nearest(refsort, pt) for pt in ptlist]
E3 = replace_with_nearest(E1, E2)
bisect
uses the classic array bisection technique to find the largest array element smaller than a given input in O(log n)
time, assuming the array is sorted. We use that to locate the two values which are immediately smaller and larger than each element of E2
.
This runs in O(n log k) time, where n
is the length of E2, and k
is the length of E1 (assuming n > k). Note that E2 doesn't need to be sorted.
Upvotes: 3
Reputation: 5732
Quick and dirty version:
E3 = [min(E2, key=lambda x: abs(x-i)) for i in E1]
For each element in E1
it finds the minimal element of E2
according to absolute distance from the E1
element.
Note that this list will contain duplicates. E.g. for your example, it returns:
[1.0, 1.1699, 1.1699, 1.1699, 1.1699]
because 1.1699 is closest to all the larger values in E1
.
A linear time, but more complex solution for sorted lists:
E3 = []
p2 = 0
for e1 in E1:
while p2 < len(E2) - 1 and abs(E2[p2] - e1) > abs(E2[p2+1] - e1):
p2 += 1
E3.append(E2[p2])
Upvotes: 3
Reputation: 206567
def closest(num, lst):
ret = lst[0]
dist = abs(lst[0]-num)
for n in lst:
if abs(n-num) < dist:
dist = abs(n-num)
ret = n
return ret
e1 = [1.0,1.3,1.69,2.1970,2.8561]
e2 = [1.00,1.04,1.08,1.1249,1.1699]
e3 = [closest(n, e2) for n in e1]
print(e3)
[1.0, 1.1699, 1.1699, 1.1699, 1.1699]
Upvotes: 0