Python 列表中重复项的索引

2025-03-05 09:18:00
admin
原创
2
摘要:问题描述:有人知道如何获取 Python 列表中重复项的索引位置吗?我尝试过这样做,但它始终只给出列表中该项目第一次出现的索引。List = ['A', 'B', 'A', 'C', 'E'] 我希望它能给我:index 0: A index 2: A 解决方案 1:您需要将可选的第二个参数传递给 in...

问题描述:

有人知道如何获取 Python 列表中重复项的索引位置吗?我尝试过这样做,但它始终只给出列表中该项目第一次出现的索引。

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

我希望它能给我:

index 0: A   
index 2: A

解决方案 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 indices(lst, item):
...   return [i for i, x in enumerate(lst) if x == item]
... 
>>> indices(List, "A")
[0, 2]

要获取所有重复项,您可以使用以下方法,但效率不高。如果效率很重要,您应该考虑 Ignacio 的解决方案。

>>> dict((x, indices(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

解决方案 3:

我对这里建议的所有解决方案进行了基准测试,并为该问题添加了另一种解决方案(在答案的末尾描述)。

基准

n首先是基准测试。我初始化一个范围内的随机整数列表[1, n/2],然后timeit调用所有算法

@Paul McGuire和 @Ignacio Vazquez-Abrams的解决方案比 100 个整数列表中其他解决方案的速度快大约两倍:

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,差异就会变得更大(顺便说一句,如果有人能解释原因我会很高兴):

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

虽然它不是最好的,但它允许我生成一个与我的问题稍微不同的结构(我需要一些类似于相同值的索引的链接列表)

解决方案 4:

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)

并从那里推断。

解决方案 5:

我认为经过多次烦恼后我找到了一个简单的解决方案:

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”)的索引

解决方案 6:

根据 lazyr 的回答,在 collections 模块中使用新的“Counter”类:

>>> 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]}

解决方案 7:

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]})

解决方案 8:

在一行中使用pandas 1.2.2numpy

 import numpy as np
 import pandas as pd
 
 idx = np.where(pd.DataFrame(List).duplicated(keep=False))

该参数keep=False将每个重复项标记为,True并将np.where()返回一个数组,其中包含数组中元素的索引True

解决方案 9:

哇,大家的答案都好长啊。我只是用了pandas dataframe、masking和duplicated函数(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')

解决方案 10:

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

#index(List, 'A')

解决方案 11:

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

解决方案 12:

这是一个好问题,并且有很多方法可以解决。

下面的代码是实现此目的的方法之一

letters = ["a", "b", "c", "d", "e", "a", "a", "b"] 

lettersIndexes = [i for i in range(len(letters))] # i created a list that contains the indexes of my previous list
counter = 0 
for item in letters: 
    if item == "a": 
        print(item, lettersIndexes[counter]) 
    counter += 1 # for each item it increases the counter which means the index 

另一种获取索引的方法,但这次将其存储在列表中

letters = ["a", "b", "c", "d", "e", "a", "a", "b"] 
lettersIndexes = [i for i in range(len(letters)) if letters[i] == "a" ] 
print(lettersIndexes) # as you can see we get a list of the indexes that we want.

再会

解决方案 13:

已经有很多回应,但我真的很喜欢这个解决方案,而且它真的很快(它使用 pandas.Series,因为它们比 pd.DataFrames 创建速度更快)。

这样做的好处是它忽略所有重复的第一个元素。

import numpy as np
import pandas as pd

lst = [0, 1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 7, 8, 9, 9]
#index 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14
#duplicates  |     |  |              |           |

indices = np.where(pd.Series(lst).duplicated())[0]

print(indices)
# [ 2  4  5 10 14]

解决方案 14:

def find_duplicate(list_):
    duplicate_list=[""]

    for k in range(len(list_)):
        if duplicate_list.__contains__(list_[k]):
            continue
        for j in range(len(list_)):
            if k == j:
                continue
            if list_[k] == list_[j]:
                duplicate_list.append(list_[j])
                print("duplicate "+str(list_.index(list_[j]))+str(list_.index(list_[k])))

解决方案 15:

这是一个适用于多个重复项的方法,您不需要指定任何值:

List = ['A', 'B', 'A', 'C', 'E', 'B'] # duplicate two 'A's two 'B's

ix_list = []
for i in range(len(List)):
    try:
        dup_ix = List[(i+1):].index(List[i]) + (i + 1) # dup onwards + (i + 1)
        ix_list.extend([i, dup_ix]) # if found no error, add i also
    except:
        pass
    
ix_list.sort()

print(ix_list)
[0, 1, 2, 5]

解决方案 16:

def dup_list(my_list, value):
    '''
    dup_list(list,value)
        This function finds the indices of values in a list including duplicated values.

        list: the list you are working on

        value: the item of the list you want to find the index of

            NB: if a value is duplcated, its indices are stored in a list
            If only one occurence of the value, the index is stored as an integer.

            Therefore use isinstance method to know how to handle the returned value
    '''
    value_list = []
    index_list = []
    index_of_duped = []

    if my_list.count(value) == 1:
        return my_list.index(value)  
        
    elif my_list.count(value) < 1:
        return 'Your argument is not in the list'

    else:
        for item in my_list:
            value_list.append(item)
            length = len(value_list)
            index = length - 1
            index_list.append(index)

            if item == value:
                index_of_duped.append(max(index_list))

        return index_of_duped

# function call eg dup_list(my_list, 'john')

解决方案 17:

如果您想获取所有不同类型的重复元素的索引,您可以尝试以下解决方案:

# note: below list has more than one kind of duplicates
List = ['A', 'B', 'A', 'C', 'E', 'E', 'A', 'B', 'A', 'A', 'C']
d1 = {item:List.count(item) for item in List}  # item and their counts
elems = list(filter(lambda x: d1[x] > 1, d1))  # get duplicate elements
d2 = dict(zip(range(0, len(List)), List))  # each item and their indices

# item and their list of duplicate indices
res = {item: list(filter(lambda x: d2[x] == item, d2)) for item in elems}

现在,如果你print(res)看到这个:

{'A': [0, 2, 6, 8, 9], 'B': [1, 7], 'C': [3, 10], 'E': [4, 5]}

解决方案 18:

def duplicates(list,dup):
  a=[list.index(dup)]
  for i in list:
     try: 
        a.append(list.index(dup,a[-1]+1))
     except:
        for i in a:
           print(f'index {i}: '+dup)
        break
duplicates(['A', 'B', 'A', 'C', 'E'],'A')

  Output:
          index 0: A
          index 2: A

解决方案 19:

使用基于setdefault实例方法的字典方法。

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

# keep track of all indices of every term
duplicates = {}
for i, key in enumerate(List):
    duplicates.setdefault(key, []).append(i)

# print only those terms with more than one index
template = 'index {}: {}'
for k, v in duplicates.items():
    if len(v) > 1:
        print(template.format(k, str(v).strip('][')))    

备注:Counterdefaultdict中的其他容器类collections是 的子类,因此也dict共享该方法setdefault

解决方案 20:

这里有很多很棒的答案。我想补充一下我的答案。我使用collections 模块的 Counter 类,用更少的代码行完成了此操作。我还使用了range(len(list))作为使用 enumerate 函数的替代方法。

import collections as col

lett_list = ['A', 'B', 'A', 'C', 'E']
lett_dict = {}
counter = col.Counter(lett_list)
elements = [i for i in counter] 
for elem in elements:
    lett_dict[elem]=[i for i in range(len(lett_list)) if lett_list[i]==elem]

print(lett_dict)

输出:{'A': [0, 2], 'B': [1], 'C': [3], 'E': [4]}

解决方案 21:

我将提到处理列表中重复项的更明显的方法。就复杂性而言,字典是可行的方法,因为每次查找都是 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])

解决方案 22:

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

解决方案 23:

我只是简单说一下:

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

输出:

 index of 1 =  0

 index of 1 =  2
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1324  
  IPD研发管理体系作为一种先进的研发管理理念和方法,对于打造优质产品体验起着至关重要的作用。它涵盖了从产品规划、研发、上市到生命周期管理的全流程,通过整合资源、优化流程、加强团队协作等方式,确保产品能够精准满足用户需求,提升用户满意度和忠诚度。IPD研发管理体系的核心原则IPD研发管理体系以市场驱动为核心原则。这意味着...
IPD集成产品开发   8  
  IPD(Integrated Product Development)产品开发流程作为一种先进的产品开发管理模式,在众多企业中得到广泛应用。它强调跨部门团队协作、并行工程以及基于市场的产品开发理念,旨在提高产品开发效率、缩短产品上市时间、提升产品质量。而成本控制在产品开发过程中至关重要,关乎企业的利润空间和市场竞争力。...
华为IPD流程   6  
  IPD(Integrated Product Development)产品开发流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。它从多个维度对产品开发过程进行优化和整合,为企业创新提供了强大的支撑。通过实施IPD产品开发流程,企业能够更加高效地将创意转化为具有市场竞争力的产品,从而在激烈的市场竞争中占据优...
华为IPD流程管理   10  
  华为作为全球知名的科技企业,其产品质量在市场上有口皆碑。华为IPD产品开发流程在确保产品质量方面发挥了至关重要的作用。IPD(Integrated Product Development)即集成产品开发,是一套先进的、成熟的产品开发管理思想、模式和方法。它打破了传统产品开发中各部门之间的壁垒,强调跨部门团队协作,从产品...
IPD集成产品开发流程   9  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用