Reputation: 21
I am trying to find the indices of all the equal elements in a matrix (n×m). For each pair of the matching cells, I will perform a specific function on them. For example:
[ [2, 1, 3], [4, 1, 5], [2, 3, 2] ]
The cell (1, 1) whose value is 2 matches with cells (3, 1) and (3, 3). I tried to do this by looping through the whole matrix twice which is far away from being efficient O(n^2 * m^2). Is there a more efficient way to do this search (at least to avoid duplicates)? Please avoid using libraries like NumPy. My code:
for i in range(n):
for k in range(n):
for j in range(m):
for l in range(m):
if matrix[i][j] == matrix[k][l]:
sum += func((i + 1, j + 1), (k + 1, l + 1))
print(sum // 2)
Upvotes: 0
Views: 394
Reputation: 1388
Same idea as in Jano's answer,but defaultdict
as it seems as a use case for it.
Build a dict
in which the 'keys' are lst elements and 'values' are a list of locations.
from collections import defaultdict
result = defaultdict(list)
for i, sublst in enumerate(lst):
for j, value in enumerate(sublst):
result[value].append((i,j))
Then you can use result
for whatever you want
>>> print('\n'.join(', '.join(str(location) for location in locations)
for locations in result.values() if len(locations) > 1))
(0, 0), (2, 0), (2, 2)
(0, 1), (1, 1)
(0, 2), (2, 1)
Note: Indexes are 0-based as per Python common usage.
Upvotes: 1
Reputation: 3066
One approach would be to store all indices for each value like this:
lst = [[2, 1, 3], [4, 1, 5], [2, 3, 2]]
result = {}
for i in range(len(lst)):
for j in range(len(lst[i])):
current = lst[i][j]
if current in result:
result[current].append((i + 1, j + 1))
else:
result[current] = [(i + 1, j + 1)]
result
The result is following dictionary storing the indices for all values:
{2: [(1, 1), (3, 1), (3, 3)],
1: [(1, 2), (2, 2)],
3: [(1, 3), (3, 2)],
4: [(2, 1)],
5: [(2, 3)]}
With this dictionary you can easily find values with multiple indices. One approach would be the following, where y
contains all combinations of two duplicate values:
from itertools import combinations
for x in result.values():
if (len(x) > 1):
combis = combinations(x, 2)
for y in combis:
print(y)
Output:
((1, 1), (3, 1))
((1, 1), (3, 3))
((3, 1), (3, 3))
((1, 2), (2, 2))
((1, 3), (3, 2))
Upvotes: 1