Możesz zacząć od precomputing macierzy odległości, co pokazują w ten answer:
import numpy as np
X = np.array([84.04467948,60.,52.42447842,39.13555678])
Y = np.array([78.86529444,52.42447842,38.74910101,21.99846595])
dist = np.abs(X[:, np.newaxis] - Y)
Teraz można obliczyć minimalne wzdłuż jednej osi (wybrałem 1
correspo nding celu znalezienia najbliższego elementu Y
dla każdego X
):
potentialClosest = dist.argmin(axis=1)
To nadal może zawierać duplikaty (w przypadku 2).Aby sprawdzić, które można znaleźć znaleźć wszystkie Y
wskaźników, które pojawiają się w potentialClosest
przy użyciu np.unique
:
closestFound, closestCounts = np.unique(potentialClosest, return_counts=True)
Teraz można sprawdzić duplikatów przez sprawdzenie czy closestFound.shape[0] == X.shape[0]
. Jeśli tak, to jesteś złoty i potentialClosest
będzie zawierać twoich partnerów dla każdego elementu w X
. W twoim przypadku 2 jeden element pojawi się dwa razy, a zatem closestFound
będzie miał tylko elementy X.shape[0]-1
, podczas gdy closestCounts
nie będzie zawierał tylko 1
s ale jednego 2
. Dla wszystkich elementów z liczyć 1
partner jest już znaleziony. Dla dwóch kandydatów z liczbą 2
, ale będziesz musiał wybrać bliżej, podczas gdy partnerem z większym dystansem będzie jeden element z Y
, który nie jest w closestFound
. To można znaleźć w:
missingPartnerIndex = np.where(
np.in1d(np.arange(Y.shape[0]), closestFound)==False
)[0][0]
Można zrobić matchin w pętli (choć nie mogą być pewne ładniejszy sposób korzystania numpy
). To rozwiązanie jest raczej brzydkie, ale działa. Wszelkie sugestie dotyczące ulepszeń są bardzo mile widziane:
partners = np.empty_like(X, dtype=int)
nonClosePartnerFound = False
for i in np.arange(X.shape[0]):
if closestCounts[closestFound==potentialClosest[i]][0]==1:
# A unique partner was found
partners[i] = potentialClosest[i]
else:
# Partner is not unique
if nonClosePartnerFound:
partners[i] = potentialClosest[i]
else:
if np.argmin(dist[:, potentialClosest[i]]) == i:
partners[i] = potentialClosest[i]
else:
partners[i] = missingPartnerIndex
nonClosePartnerFound = True
print(partners)
Ta odpowiedź będzie działać tylko wtedy, gdy tylko jedna para nie jest zamknięta. Jeśli tak nie jest, musisz określić, jak znaleźć właściwego partnera dla wielu niezamkniętych elementów. Niestety, nie jest to rozwiązanie bardzo ogólne ani bardzo ładne, ale mam nadzieję, że okaże się pomocne.
Jaki jest twój kod funkcji? – grael
Proste podejście złożoności kwadratowej: dla każdego elementu w X, wyszukaj najbliższy y w Y, oznacz jako już zrobione (nie można go ponownie wybrać) i kontynuuj. – sascha
@asascha Twoje podejście nie działa dla drugiego przykładu. Załóżmy, że masz 60. Najbliższa liczba w innej tablicy to 52. Więc weź to i nic innego nie może być teraz sparowane, ale tak naprawdę to nie jest dobre rozwiązanie, ponieważ 60 powinno być sparowane z 21 (i 52 powinien być sparowany z innym 52 w pierwszej tablicy). – eiKatte