1

Say I have a list like this:

l = [1, 2, 3, 4, 5, 3]

how do I get the indexes of those 3s that have been repeated?

4 Answers4

1

First you need to figure out which elements are repeated and where. I do it by indexing it in a dictionary.

Then you need to extract all repeated values.

from collections import defaultdict

l = [1, 2, 3, 4, 5, 3]
_indices = defaultdict(list)

for index, item in enumerate(l):
    _indices[item].append(index)

for key, value in _indices.items():
    if len(value) > 1:
        # Do something when them
        print(key, value)

Output:

3 [2, 5]

Another would be to filter them out like so:

duplicates_dict = {key: indices for key, indices in _indices.items() if len(indices) > 1}
Bharel
  • 23,672
  • 5
  • 40
  • 80
1

you could use a dictionary comprehension to get all the repeated numbers and their indexes in one go:

L = [1, 2, 3, 4, 5, 3, 8, 9, 9, 8, 9]

R = { n:rep[n] for rep in [{}] for i,n in enumerate(L) 
      if rep.setdefault(n,[]).append(i) or len(rep[n])==2 }

print(R)

{3: [2, 5], 
 9: [7, 8, 10], 
 8: [6, 9]}

The equivalent using a for loop would be:

R = dict()
for i,n in enumerate(L):
    R.setdefault(n,[]).append(i)
R = {n:rep for n,rep in R.items() if len(rep)>1}

Counter from collections could be used to avoid the unnecessary creation of single item lists:

from collections import Counter
counts = Counter(L)
R = dict()
for i,n in enumerate(L):
    if counts[n]>1:
       R.setdefault(n,[]).append(i)
Alain T.
  • 40,517
  • 4
  • 31
  • 51
  • 1
    With all due respect, I understand the need to make everything a one liner but this code is terribly inefficient and hard to understand. I'm not sure if there's any way to improve this one liner tbh. – Bharel Dec 26 '21 at 17:10
  • While I agree that it is hard to read (and probably not something I would use in production code), it is just as efficient as the for-loop version. It only outputs key:values once per duplicate number and uses an internal dictionary that holds the same amount of data as the initial R in the for-loop (and is updated the same way). – Alain T. Dec 26 '21 at 17:24
  • 2
    Your one-liner is not as efficient as a loop: It creates a new list for every item, including duplicates. It causes 2 dictionary lookups for every item, 3 if the item exists more than once. – Bharel Dec 26 '21 at 17:38
  • You are right, I didn't consider the extra lookups. – Alain T. Dec 26 '21 at 17:42
1

find deplicates and loop through the list to find the corresponding index locations. Not the most efficient, but works

input_list = [1,4,5,7,1,2,4]
duplicates = input_list.copy()

for x in set(duplicates):
    duplicates.remove(x)

duplicates = list(set(duplicates))
dict_duplicates = {}
for d in duplicates:
    l_ind = []
    dict_duplicates[d] = l_ind    
    for i in range(len(input_list)):
        if d == input_list[i]:
            l_ind.append(i)
dict_duplicates            
karas27
  • 335
  • 1
  • 5
  • 15
1

If you want to access and use all of them, you can iterate over the position on the list, and specify this position in 'index' function.

l = [1, 2, 3, 4, 5, 3]
repeated_indexes = []
pos = 0 
for item in l:
    if item == 3:
        index = l.index(item, pos)
        repeated_indexes.append(index)
    pos +=1

See documentation of index function here : https://docs.python.org/3/library/array.html#array.array.index

Marian
  • 11
  • 1