[英]Most efficient computational way in python find pairs in a list of pairs
[英]Efficient way to find all the pairs in a list without using nested loop
假設我有一個存儲許多二維點的列表。 在這個列表中,一些位置存儲了相同的點,將存儲相同點的位置的索引視為索引對。 我想找到列表中的所有對並返回所有 2 x 2 索引對。 列表中可能有一些點重復了兩次以上,但只需要將第一個匹配項視為一對。
例如,在下面的列表中,我總共有 9 個點,並且有 5 個位置包含重復點。 索引 0、3 和 7 存儲相同的點 ( [1, 1]
),索引 1 和 6 存儲相同的點 ( [2, 3]
)。
[[1, 1], [2, 3], [1, 4], [1, 1], [10, 3], [5, 2], [2, 3], [1, 1], [3, 4]]
因此,對於此列表,我想將索引對返回為(索引 0,索引 3)和(索引 1,索引 6)。 我能想出的唯一解決方案是通過嵌套循環來實現,我將其編碼如下
A = np.array([[1, 1], [2, 3], [1, 4], [1, 1], [10, 3], [5, 2], [2, 3], [1, 1], [3, 4]], dtype=int)
# I don't want to modified the original list, looping through a index list insted.
Index = np.arange(0, A.shape[0], 1, dtype=int)
Pair = [] # for store the index pair
while Index.size != 0:
current_index = Index[0]
pi = A[current_index]
Index = np.delete(Index, 0, 0)
for j in range(Index.shape[0]):
pj = A[Index[j]]
distance = linalg.norm(pi - pj, ord=2, keepdims=True)
if distance == 0:
Pair.append([current_index, Index[j]])
Index = np.delete(Index, j, 0)
break
雖然這段代碼對我有用,但時間復雜度是O(n^2)
,其中n == len(A)
,我想知道是否有更有效的方法來以較低的時間復雜度完成這項工作。 感謝您的任何想法和幫助。
您可以使用字典來跟蹤每個點的索引。
然后,您可以遍歷字典中的項目,打印出與多次出現的點對應的索引。 此過程的運行時間與A
中的點數成線性關系,而不是二次關系:
points = {}
for index, point in enumerate(A):
point_tuple = tuple(point)
if point_tuple not in points:
points[point_tuple] = []
points[point_tuple].append(index)
for point, indices in points.items():
if len(indices) > 1:
print(indices)
這打印出來:
[0, 3, 7]
[1, 6]
如果您只想要出現點的前兩個索引,則可以使用print(indices[:2])
而不是print(indices)
。
這類似於另一個答案,但由於在多對的情況下您只需要前兩個,因此您可以在一次迭代中完成。 在 dict 中的適當鍵下添加索引,並在(且僅當)有兩點時生成索引:
from collections import defaultdict
l = [[1, 1], [2, 3], [1, 4], [1, 1], [10, 3], [5, 2], [2, 3], [1, 1], [3, 4]]
def get_pairs(l):
ind = defaultdict(list)
for i, pair in enumerate(l):
t = tuple(pair)
ind[t].append(i)
if len(ind[t]) == 2:
yield list(ind[t])
list(get_pairs(l))
# [[0, 3], [1, 6]]
一個沒有循環的純 Numpy 解決方案(迄今為止唯一的一個)是使用np.unique
兩次,其中一個技巧是刪除在兩次搜索之間找到的第一個項目。 此解決方案假設可以設置標記(例如 -1,integer 的最小值,NaN),這通常不是問題(如果需要,您可以使用更大的類型)。
A = np.array([[1, 1], [2, 3], [1, 4], [1, 1], [10, 3], [5, 2], [2, 3], [1, 1], [3, 4]], dtype=int)
# Copy the array not to mutate it
tmp = A.copy()
# Find the location of unique values
pair1, index1 = np.unique(tmp, return_index=True, axis=0)
# Discard the element found assuming -1 is never stored in A
INT_MIN = np.iinfo(A.dtype).min
tmp[index1] = INT_MIN
# Find the location of duplicated values
pair2, index2 = np.unique(tmp, return_index=True, axis=0)
# Extract the indices that share the same pair of values found
left = index1[np.isin(pair1, pair2).all(axis=1)]
right = index2[np.isin(pair2, pair1).all(axis=1)]
# Combine the each left index with each right index
result = np.hstack((left[:,None], right[:,None]))
# result = array([[0, 3],
# [1, 6]])
該解決方案應在O(n log n)
時間內運行,因為np.unique
在內部使用基本排序(更具體地說是快速排序)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.