Reputation: 11
I'm trying to implement a logic where I'm trying to subtract each element of an array from every other element of the array and then find the minimum difference of the result.
eg : a=[10,7,3,6]
so I subtract 10 from every other element of the array to begin with (result will be 3,7,4) then move over to the next element which is 7 and then subtract it from the rest of the elements of the array (result will be 4,1), take the next element i.e 3 and subtract it with the remaining element 6 (result : -3). Note: I'm need to take absolute values of the result for my actual problem. Now as you can see, the minimum difference of the result of this subtraction process is 1.
I have managed to write a code till this point. However I also need to find the indices of numbers for which I have got the minimum difference result value as 1 (i.e indices of 7 and 6 in this example)
Does anyone how if there is any function to implement this in NumPy? I have tried using argwhere() with no success.
Upvotes: 1
Views: 2144
Reputation: 25813
You might want to consider a different algorithm for finding the closest pair. Your current algorithm compares every pair of values, when you really only need to compare each value to the next biggest value. You can do that by doing something like: 1) sort your array a
2) Compare neighbors in a
to find the smallest difference. This might help you get started.
import numpy as np
a = np.array([10, 7, 3, 6])
index = np.argsort(a)
a_sorted = a[index]
diff = a_sorted[1:] - a_sorted[:-1]
Also to find where a == 6 you can do this (but you probably shouldn't need this):
where_a_is_6 = np.where(a == 6)[0]
Upvotes: 2
Reputation: 114811
Here's a somewhat dense one-liner that doesn't use NumPy:
>>> from itertools import combinations
>>> a = [10, 7, 3, 6]
>>> closest_pair = min((abs(x-y), (i, j)) for (i,x), (j, y) in combinations(enumerate(a), 2))[1]
>>> closest_pair
(1, 3)
Here's how it works...
combinations
is used to create all the pairs:
>>> list(combinations(a, 2))
[(10, 7), (10, 3), (10, 6), (7, 3), (7, 6), (3, 6)]
We need the indices of the elements, so that is modified to:
>>> list(combinations(enumerate(a), 2))
[((0, 10), (1, 7)),
((0, 10), (2, 3)),
((0, 10), (3, 6)),
((1, 7), (2, 3)),
((1, 7), (3, 6)),
((2, 3), (3, 6))]
The list comprehension acts on this result and forms a new list of absolute differences and the corresponding pairs of indices:
>>> [(abs(x - y), (i, j)) for (i,x), (j, y) in combinations(enumerate(a), 2)]
[(3, (0, 1)), (7, (0, 2)), (4, (0, 3)), (4, (1, 2)), (1, (1, 3)), (3, (2, 3))]
Taking the minimum gives the tuple whose first value is the minimum absolute distance and whose second value is the tuple of the indices:
>>> min((abs(x - y), (i, j)) for (i,x), (j, y) in combinations(enumerate(a), 2))
(1, (1, 3))
Finally, pull out just the indices from that result:
>>> min((abs(x - y), (i, j)) for (i,x), (j, y) in combinations(enumerate(a), 2))[1]
(1, 3)
Upvotes: 0