有谁知道如何在python列表中获取重复项的索引位置?我试过这样做,它只给我一个列表中项目第一次出现的索引.
List = ['A', 'B', 'A', 'C', 'E']
Run Code Online (Sandbox Code Playgroud)
我希望它能给我:
index 0: A
index 2: A
Run Code Online (Sandbox Code Playgroud)
Pau*_*McG 44
您希望将可选的第二个参数传递给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'))
Run Code Online (Sandbox Code Playgroud)
打印:
[1, 3, 5, 11, 15, 22]
Run Code Online (Sandbox Code Playgroud)
您可以在一次传递源中一次性找到所有重复项,方法是使用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)
Run Code Online (Sandbox Code Playgroud)
打印:
('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])
Run Code Online (Sandbox Code Playgroud)
如果要针对同一源重复测试各种键,可以使用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))
Run Code Online (Sandbox Code Playgroud)
打印:
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]
Run Code Online (Sandbox Code Playgroud)
Lau*_*low 16
>>> def duplicates(lst, item):
... return [i for i, x in enumerate(lst) if x == item]
...
>>> duplicates(List, "A")
[0, 2]
Run Code Online (Sandbox Code Playgroud)
要获得所有重复项,您可以使用以下方法,但效率不高.如果效率很重要,您应该考虑使用Ignacio的解决方案.
>>> dict((x, duplicates(List, x)) for x in set(List) if List.count(x) > 1)
{'A': [0, 2]}
Run Code Online (Sandbox Code Playgroud)
至于使用替代index
方法解决它list
,该方法采用第二个可选参数指示从哪里开始,因此您可以使用前一个索引加1重复调用它.
>>> List.index("A")
0
>>> List.index("A", 1)
2
Run Code Online (Sandbox Code Playgroud)
编辑修复了评论中引发的问题.
Ign*_*ams 13
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)
Run Code Online (Sandbox Code Playgroud)
并从那里推断.
Rus*_*Bes 10
我对此处建议的所有解决方案进行了基准测试,并为此问题添加了另一种解决方案(在答案的最后描述).
首先是基准.我初始化一个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
####################
Run Code Online (Sandbox Code Playgroud)
如果您将项目数量更改为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
####################
Run Code Online (Sandbox Code Playgroud)
在更大的列表中,@ 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
####################
Run Code Online (Sandbox Code Playgroud)
基准测试的完整代码就在这里
这是我对同一问题的解决方案:
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
Run Code Online (Sandbox Code Playgroud)
虽然它不是最好的,它允许我生成我的问题所需的一点点不同的结构(我需要类似于相同值的索引的链接列表)
在收集模块中使用新的"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]}
Run Code Online (Sandbox Code Playgroud)
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]})
Run Code Online (Sandbox Code Playgroud)
稍微更正交(因此更有用)的实现将是:
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]})
Run Code Online (Sandbox Code Playgroud)
我想在经过多次激怒之后我找到了一个简单的解决方案:
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)
Run Code Online (Sandbox Code Playgroud)
这将打印一个列表,为您提供特定元素的索引("elem")
归档时间: |
|
查看次数: |
77921 次 |
最近记录: |