Python—如果在列表中出现两次,则在两个值的索引之间删除
标题确实令人困惑,所以这里有一个例子:假设我有一个值列表[1,2,3,2,1,4,5,6,7,8]。我想删除列表中两个1之间的值,通过python方法,它也会删除第一个1并输出[1,4,5,6,7,8]。不幸的是,由于我缺乏pythonic能力,我只能制作一些删除第一组的东西:Python—如果在列表中出现两次,则在两个值的索引之间删除,python,indexing,Python,Indexing,标题确实令人困惑,所以这里有一个例子:假设我有一个值列表[1,2,3,2,1,4,5,6,7,8]。我想删除列表中两个1之间的值,通过python方法,它也会删除第一个1并输出[1,4,5,6,7,8]。不幸的是,由于我缺乏pythonic能力,我只能制作一些删除第一组的东西: a = [1,2,3,2,1,4,5,6,7] uniques = [] junks = [] for value in a: junks.append(value) if value not in un
a = [1,2,3,2,1,4,5,6,7]
uniques = []
junks = []
for value in a:
junks.append(value)
if value not in uniques:
uniques.append(value)
for value in uniques:
junks.remove(value)
for value in junks:
a.remove(value)
a.remove(value)
a[0] = 1
print(a)
[1,4,5,6,7]
适用于第一个双匹配项,而不适用于较大列表中的下一个匹配项。我有一个想法,就是在第一次出现的索引和第二次出现的索引之间删除,这将保留第二次出现的索引,而不是让我做一些愚蠢的事情,比如[0]=1,但我真的不知道如何实现它。如果要查找唯一的元素,可以使用set和list
mylist = list(set(mylist))
如果要查找唯一的元素,可以使用set和list
mylist = list(set(mylist))
这是否符合您的要求:
a = [1, 2, 3, 2, 1, 4, 5, 6, 7, 8]
def f(l):
x = l.copy()
for i in l:
if x.count(i) > 1:
first_index = x.index(i)
second_index = x.index(i, first_index + 1)
x = x[:first_index] + x[second_index:]
return x
所以fa的输出是[1,4,5,6,7,8],f[1,2,3,2,1,4,5,6,7,8,7,6,5,15,16]的输出是[1,4,5,15,16]。
a = [1, 2, 3, 2, 1, 4, 5, 6, 7, 8]
def f(l):
x = l.copy()
for i in l:
if x.count(i) > 1:
first_index = x.index(i)
second_index = x.index(i, first_index + 1)
x = x[:first_index] + x[second_index:]
return x
所以fa的输出是[1,4,5,6,7,8],而f[1,2,3,2,1,4,5,6,7,8,7,6,5,15,16]的输出是[1,4,5,15,16]
一个更有效的解决办法是
a = [1, 2, 3, 2, 1, 4, 5, 6, 7, 8, 7, 6, 5, 15, 16]
pos1 = 0
while pos1 < len(a):
if a[pos1] in a[pos1+1:]:
pos2 = a.index(a[pos1], pos1+1)
a = a[:pos1]+a[pos2:]
pos1 += 1
print a #[1, 4, 5, 15, 16]
一个更有效的解决办法是
a = [1, 2, 3, 2, 1, 4, 5, 6, 7, 8, 7, 6, 5, 15, 16]
pos1 = 0
while pos1 < len(a):
if a[pos1] in a[pos1+1:]:
pos2 = a.index(a[pos1], pos1+1)
a = a[:pos1]+a[pos2:]
pos1 += 1
print a #[1, 4, 5, 15, 16]
这可能不是最有效的方法,但希望能有所帮助
你不能检查一下某个东西是否出现了两次吗?如果出现了,你有firstIndex,secondIndex,然后:
a=[1,2,3,4,5,1,7,8,9]
b=[]
然后用一种方法得到重复数的第一个和第二个索引
对于范围为0的索引,lena:
打印索引
如果index>firstIndex和index这可能不是最有效的方法,但希望能有所帮助
你不能检查一下某个东西是否出现了两次吗?如果出现了,你有firstIndex,secondIndex,然后:
a=[1,2,3,4,5,1,7,8,9]
b=[]
然后用一种方法得到重复数的第一个和第二个索引
对于范围为0的索引,lena:
打印索引
如果index>firstIndex和index完成您需要的工作: 重复值的第一个和最后一个位置 之间的所有索引,以删除它们 有趣的是,您可以简单地告诉python这样做:
# we can use a 'smart' dictionary, that can construct default value:
from collections import defaultdict
# and 'chain' to flatten lists (ranges)
from itertools import chain
a = [1, 2, 3, 2, 1, 4, 5, 6, 7]
# build dictionary where each number is key, and value is list of positions:
index = defaultdict(list)
for i, item in enumerate(a):
index[item].append(i)
# let's take first only and last index for non-single values
edges = ((pos[0], pos[-1]) for pos in index.values() if len(pos) > 1)
# we can use range() to get us all index positions in-between
# ...use chain.from_iterable to flatten our list
# ...and make set of it for faster lookup:
to_remove = set(chain.from_iterable(range(start, end)
for start, end in edges))
result = [item for i, item in enumerate(a) if i not in to_remove]
# expected: [1, 4, 5, 6, 7]
print result
当然,您可以将其缩短:
index = defaultdict(list)
for i, item in enumerate([1, 2, 3, 2, 1, 4, 5, 6, 7]):
index[item].append(i)
to_remove = set(chain.from_iterable(range(pos[0], pos[-1])
for pos in index.values() if len(pos) > 1))
print [item for i, item in enumerate(a) if i not in to_remove]
此解决方案具有线性复杂性,应该非常快。代价是
字典和集合的额外内存,所以您应该小心巨大的数据集。但是,如果您有大量数据,使用lst.index的其他解决方案无论如何都会阻塞,因为它们在^2上,有大量的解引用和函数调用。要完成您需要的工作: 重复值的第一个和最后一个位置 之间的所有索引,以删除它们 有趣的是,您可以简单地告诉python这样做:
# we can use a 'smart' dictionary, that can construct default value:
from collections import defaultdict
# and 'chain' to flatten lists (ranges)
from itertools import chain
a = [1, 2, 3, 2, 1, 4, 5, 6, 7]
# build dictionary where each number is key, and value is list of positions:
index = defaultdict(list)
for i, item in enumerate(a):
index[item].append(i)
# let's take first only and last index for non-single values
edges = ((pos[0], pos[-1]) for pos in index.values() if len(pos) > 1)
# we can use range() to get us all index positions in-between
# ...use chain.from_iterable to flatten our list
# ...and make set of it for faster lookup:
to_remove = set(chain.from_iterable(range(start, end)
for start, end in edges))
result = [item for i, item in enumerate(a) if i not in to_remove]
# expected: [1, 4, 5, 6, 7]
print result
当然,您可以将其缩短:
index = defaultdict(list)
for i, item in enumerate([1, 2, 3, 2, 1, 4, 5, 6, 7]):
index[item].append(i)
to_remove = set(chain.from_iterable(range(pos[0], pos[-1])
for pos in index.values() if len(pos) > 1))
print [item for i, item in enumerate(a) if i not in to_remove]
此解决方案具有线性复杂性,应该非常快。代价是
字典和集合的额外内存,所以您应该小心巨大的数据集。但是如果您有大量数据,使用lst.index的其他解决方案无论如何都会阻塞,因为它们在^2上,有大量的解引用和函数调用。这样做不会保留任何边值,因此对于[1,2,3,2,1,4,5,6,7],它将返回[4,5,6,7],而不是[1,4,5,6,7],这样做不会保留任何边值,对于[1,2,3,1,1,4,5,6,7]它将返回[4,5,6,7]而不是[1,4,5,6,7]Nah,在这种情况下,所需的输出是[1,4,5,6,7,8]。如果我们有一个更大的列表,比如a=[1,2,3,2,1,4,5,6,7,8,7,6,5,15,16],那么它也不起作用。在这种情况下,我也希望在5之间删除。@Sundrah那么你想在所有重复值之间删除吗?你不想同时保留两个1,只保留第一个,对吗?[1,2,3,1,2,3]的期望输出是什么?@Markus Meskanen是的,就是这样。@Julien Spronck这种列表在我做的算法中永远不会出现。不,在这种情况下,期望输出是[1,4,5,6,7,8]。如果我们有一个更大的列表,比如a=[1,2,3,2,1,4,5,6,7,8,7,6,5,15,16],那么它也不起作用。在这种情况下,我也希望在5之间删除。@Sundrah那么你想在所有重复值之间删除吗?你不想同时保留两个1,只保留第一个,对吗?[1,2,3,1,2,3]的期望输出是什么?@Markus Meskanen是的,就是这样。@Julien Spronck这种列表在我做的算法中永远不会出现。@Sundah这就是你想要的吗?是的,是的。他们真的需要做一件事,你可以标记一个以上的答案正确。非常感谢您的时间。您真的应该在这里使用for循环:对于lena中的pos1:因为您只是在while循环中调用pos1+=1。我不使用for循环的原因是因为我想在不创建副本的情况下更改ait@Sundrah这就是你想要的吗?是的。他们真的需要做一件事,你可以标记一个以上的答案正确。非常感谢你的时间。你应该
我在这里使用for循环:对于lena中的pos1:sinc eyou反正只是在while循环中调用pos1+=1。我不使用for循环的原因是我想更改a而不创建它的副本