Suvo
Suvo

Reputation: 1448

comparing two different lists

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

Answers (3)

nneonneo
nneonneo

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

otus
otus

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

R Sahu
R Sahu

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

Related Questions