Подтвердить что ты не робот

Индекс элементов дубликатов в списке python

Кто-нибудь знает, как я могу получить позицию индекса дублированных элементов в списке python? Я попытался сделать это, и он продолжает давать мне только индекс 1-го вхождения элемента в список.

List = ['A', 'B', 'A', 'C', 'E']

Я хочу, чтобы он дал мне:

index 0: A   
index 2: A
4b9b3361

Ответ 1

Вы хотите передать необязательный второй параметр index, место, где вы хотите, чтобы index начал искать. После того, как вы найдете каждое совпадение, сбросьте этот параметр в местоположение сразу после найденного совпадения.

def list_duplicates_of(seq,item):
    start_at = -1
    locs = []
    while True:
        try:
            loc = seq.index(item,start_at+1)
        except ValueError:
            break
        else:
            locs.append(loc)
            start_at = loc
    return locs

source = "ABABDBAAEDSBQEWBAFLSAFB"
print(list_duplicates_of(source, 'B'))

Печать:

[1, 3, 5, 11, 15, 22]

Вы можете найти все дубликаты одновременно за один проход через источник, используя defaultdict, чтобы сохранить список всех просмотренных местоположений для любого элемента, и возвращая те элементы, которые были просмотрены более одного раза.

from collections import defaultdict

def list_duplicates(seq):
    tally = defaultdict(list)
    for i,item in enumerate(seq):
        tally[item].append(i)
    return ((key,locs) for key,locs in tally.items() 
                            if len(locs)>1)

for dup in sorted(list_duplicates(source)):
    print(dup)

Печать:

('A', [0, 2, 6, 7, 16, 20])
('B', [1, 3, 5, 11, 15, 22])
('D', [4, 9])
('E', [8, 13])
('F', [17, 21])
('S', [10, 19])

Если вы хотите выполнить повторное тестирование для различных ключей в одном и том же источнике, вы можете использовать functools.partial для создания новой переменной функции, используя "частично полный" список аргументов, то есть, указав seq, но пропуская элемент для поиска за:

from functools import partial
dups_in_source = partial(list_duplicates_of, source)

for c in "ABDEFS":
    print(c, dups_in_source(c))

Печать:

A [0, 2, 6, 7, 16, 20]
B [1, 3, 5, 11, 15, 22]
D [4, 9]
E [8, 13]
F [17, 21]
S [10, 19]

Ответ 2

>>> def duplicates(lst, item):
...   return [i for i, x in enumerate(lst) if x == item]
... 
>>> duplicates(List, "A")
[0, 2]

Чтобы получить все дубликаты, вы можете использовать метод ниже, но он не очень эффективен. Если эффективность важна, вы должны вместо этого использовать решение Игнасио.

>>> dict((x, duplicates(List, x)) for x in set(List) if List.count(x) > 1)
{'A': [0, 2]}

Для решения этого метода вместо index метода list этот метод принимает второй необязательный аргумент, указывающий, с чего начать, поэтому вы можете просто повторно называть его с предыдущим индексом плюс 1.

>>> List.index("A")
0
>>> List.index("A", 1)
2

EDIT Исправлена ​​проблема, возникающая в комментариях.

Ответ 3

dups = collections.defaultdict(list)
for i, e in enumerate(L):
  dups[e].append(i)
for k, v in sorted(dups.iteritems()):
  if len(v) >= 2:
    print '%s: %r' % (k, v)

И экстраполируйте оттуда.

Ответ 4

Я сделал контрольный образец всех предложенных решений, а также добавил еще одно решение этой проблемы (описано в конце ответа).

Бенчмарки

Во-первых, эталонные тесты. Я инициализирую список n случайных ints в диапазоне [1, n/2], а затем вызовите timeit по всем алгоритмам

Решения @Paul McGuire и @Игнасио Васкес-Абрамс работают примерно в два раза быстрее, чем оставайтесь в списке из 100 ints:

Testing algorithm on the list of 100 items using 10000 loops
Algorithm: dupl_eat
Timing: 1.46247477189
####################
Algorithm: dupl_utdemir
Timing: 2.93324529055
####################
Algorithm: dupl_lthaulow
Timing: 3.89198786645
####################
Algorithm: dupl_pmcguire
Timing: 0.583058259784
####################
Algorithm: dupl_ivazques_abrams
Timing: 0.645062989076
####################
Algorithm: dupl_rbespal
Timing: 1.06523873786
####################

Если вы меняете количество предметов на 1000, разница становится намного больше (BTW, я буду рад, если кто-нибудь сможет объяснить почему):

Testing algorithm on the list of 1000 items using 1000 loops
Algorithm: dupl_eat
Timing: 5.46171654555
####################
Algorithm: dupl_utdemir
Timing: 25.5582547323
####################
Algorithm: dupl_lthaulow
Timing: 39.284285326
####################
Algorithm: dupl_pmcguire
Timing: 0.56558489513
####################
Algorithm: dupl_ivazques_abrams
Timing: 0.615980005148
####################
Algorithm: dupl_rbespal
Timing: 1.21610942322
####################

В больших списках решение @Paul McGuire остается наиболее эффективным, и у моего алгоритма возникают проблемы.

Testing algorithm on the list of 1000000 items using 1 loops
Algorithm: dupl_pmcguire
Timing: 1.5019953958
####################
Algorithm: dupl_ivazques_abrams
Timing: 1.70856155898
####################
Algorithm: dupl_rbespal
Timing: 3.95820421595
####################

Полный код эталона здесь

Другой алгоритм

Вот мое решение той же проблемы:

def dupl_rbespal(c):
    alreadyAdded = False
    dupl_c = dict()
    sorted_ind_c = sorted(range(len(c)), key=lambda x: c[x]) # sort incoming list but save the indexes of sorted items

    for i in xrange(len(c) - 1): # loop over indexes of sorted items
        if c[sorted_ind_c[i]] == c[sorted_ind_c[i+1]]: # if two consecutive indexes point to the same value, add it to the duplicates
            if not alreadyAdded:
                dupl_c[c[sorted_ind_c[i]]] = [sorted_ind_c[i], sorted_ind_c[i+1]]
                alreadyAdded = True
            else:
                dupl_c[c[sorted_ind_c[i]]].append( sorted_ind_c[i+1] )
        else:
            alreadyAdded = False
    return dupl_c

Хотя это не лучшее, это позволило мне создать немного другую структуру, необходимую для моей проблемы (мне нужно было что-то вроде связанного списка индексов того же значения)

Ответ 5

Использование нового класса "Counter" в модуле коллекций на основе ответа lazyr:

>>> import collections
>>> def duplicates(n): #n="123123123"
...     counter=collections.Counter(n) #{'1': 3, '3': 3, '2': 3}
...     dups=[i for i in counter if counter[i]!=1] #['1','3','2']
...     result={}
...     for item in dups:
...             result[item]=[i for i,j in enumerate(n) if j==item] 
...     return result
... 
>>> duplicates("123123123")
{'1': [0, 3, 6], '3': [2, 5, 8], '2': [1, 4, 7]}

Ответ 6

from collections import Counter, defaultdict

def duplicates(lst):
    cnt= Counter(lst)
    return [key for key in cnt.keys() if cnt[key]> 1]

def duplicates_indices(lst):
    dup, ind= duplicates(lst), defaultdict(list)
    for i, v in enumerate(lst):
        if v in dup: ind[v].append(i)
    return ind

lst= ['a', 'b', 'a', 'c', 'b', 'a', 'e']
print duplicates(lst) # ['a', 'b']
print duplicates_indices(lst) # ..., {'a': [0, 2, 5], 'b': [1, 4]})

Несколько более ортогональная (и, следовательно, более полезная) реализация будет:

from collections import Counter, defaultdict

def duplicates(lst):
    cnt= Counter(lst)
    return [key for key in cnt.keys() if cnt[key]> 1]

def indices(lst, items= None):
    items, ind= set(lst) if items is None else items, defaultdict(list)
    for i, v in enumerate(lst):
        if v in items: ind[v].append(i)
    return ind

lst= ['a', 'b', 'a', 'c', 'b', 'a', 'e']
print indices(lst, duplicates(lst)) # ..., {'a': [0, 2, 5], 'b': [1, 4]})

Ответ 7

Я думаю, что я нашел простое решение после большого раздражения:

if elem in string_list:
    counter = 0
    elem_pos = []
    for i in string_list:
        if i == elem:
            elem_pos.append(counter)
        counter = counter + 1
    print(elem_pos)

Это печатает список, в котором указаны индексы определенного элемента ( "elem" )

Ответ 8

Вау, каждый ответ так долго. Я просто использовал pandas dataframe, masking и дублированную функцию (keep=False помечает все дубликаты как True, а не только первый или последний):

import pandas as pd
import numpy as np
np.random.seed(42)  # make results reproducible

int_df = pd.DataFrame({'int_list': np.random.randint(1, 20, size=10)})
dupes = int_df['int_list'].duplicated(keep=False)
print(int_df['int_list'][dupes].index)

Это должно вернуть Int64Index([0, 2, 3, 4, 6, 7, 9], dtype='int64').

Ответ 9

Я расскажу о более очевидном способе работы с дубликатами в списках. С точки зрения сложности словари - это путь, потому что каждый поиск - O (1). Вы можете быть более умными, если вас интересуют только дубликаты...

my_list = [1,1,2,3,4,5,5]
my_dict = {}
for (ind,elem) in enumerate(my_list):
    if elem in my_dict:
        my_dict[elem].append(ind)
    else:
        my_dict.update({elem:[ind]})

for key,value in my_dict.iteritems():
    if len(value) > 1:
        print "key(%s) has indices (%s)" %(key,value)

который печатает следующее:

key(1) has indices ([0, 1])
key(5) has indices ([5, 6])

Ответ 10

string_list = ['A', 'B', 'C', 'B', 'D', 'B']
pos_list = []
for i in range(len(string_list)):
    if string_list[i] = ='B':
        pos_list.append(i)
print pos_list

Ответ 11

a= [2,3,4,5,6,2,3,2,4,2]
search=2
pos=0
positions=[]

while (search in a):
    pos+=a.index(search)
    positions.append(pos)
    a=a[a.index(search)+1:]
    pos+=1

print "search found at:",positions

Ответ 12

def index(arr, num):
    for i, x in enumerate(arr):
        if x == num:
            print(x, i)

#index(List, 'A')

Ответ 13

Вы также можете использовать списочные выражения следующим образом:

List = ['A', 'B', 'A', 'C', 'E']

## you could pass a variable instead of "A"
idx = [i for i in range(len(List)) if List[i] == "A"] 

print(idx)
[0, 2]

Ответ 14

Привет, ребята, я просто делаю это просто:

i = [1,2,1,3]
k = 0
for ii in i:    
if ii == 1 :
    print ("index of 1 = ", k)
k = k+1

вывод:

индекс 1 = 0

индекс 1 = 2