Python 在列表中查找重复的数字并使其唯一
我正在尝试实现一个遗传算法,我的交叉函数需要这个。我需要弄清楚的是以下几点。 如果我有名单Python 在列表中查找重复的数字并使其唯一,python,Python,我正在尝试实现一个遗传算法,我的交叉函数需要这个。我需要弄清楚的是以下几点。 如果我有名单 [0, 1, 6, 7, 5, 4, 3, 2, 1] 它有重复的元素。我想以名单结束 [0, 8, 6, 7, 5, 4, 3, 2, 1] 我得到这个列表的原因是我从左到右查看每个元素。我在索引1中看到了数字“1”,它也存在于列表中。因此,我将其更改为不在列表中的元素。列表中最小的元素是0,最大的元素是len(list)-1 在这种情况下,列表的顺序很重要。因此,我不认为将其转换为集合是合适的。我
[0, 1, 6, 7, 5, 4, 3, 2, 1]
它有重复的元素。我想以名单结束
[0, 8, 6, 7, 5, 4, 3, 2, 1]
我得到这个列表的原因是我从左到右查看每个元素。我在索引1中看到了数字“1”,它也存在于列表中。因此,我将其更改为不在列表中的元素。列表中最小的元素是0,最大的元素是len(list)-1
在这种情况下,列表的顺序很重要。因此,我不认为将其转换为集合是合适的。我不想失去元素的顺序。我只是在更改列表中已经重复的元素
另一个例子是
[0, 1, 2, 7, 3, 4, 3, 2, 1]
将成为
[0, 5, 6, 7, 8, 4, 3, 2, 1]
这里发生的事情是,我在索引1处看到了数字1,并且意识到从0到8的范围内,我错过了数字5。所以1被5取代了。同样地,我对索引2也这样做了,我将其替换为6。最后,我对索引4做了这项工作,它最初是3,但被替换为8,因为它是重复的
我的想法是增加重复的数字,然后检查它是否重复,并重复,直到列表中的每个元素都是唯一的。然而,我想不出一个办法来做到这一点 因此,除非我弄错了,否则在你选择替换的数字背后没有真正的方法,只是你认为缺少的一个。如果是这种情况,那么这将产生所需的结果
l = [0, 1, 2, 7, 3, 4, 3, 2, 1]
missing = [n for n in range(len(l)) if n not in set(l)]
for num in l:
if l.count(num) > 1:
ix = l.index(num)
try:
l[ix] = missing.pop(0)
except IndexError:
break
print l
>>[0, 5, 6, 7, 8, 4, 3, 2, 1]
更新:这可以通过查找给定条件的索引来实现
import itertools as it
import collections as ct
from more_itertools import locate
def replace_repeated(lst):
"""Return a list of unique values with a range ~ list size."""
def excluded_indices():
"""Yield indices of all but the index of the last repeated element."""
for i, n in repeated.items():
yield from it.islice(locate(lst, pred=lambda x: x == i), 0, n-1)
repeated = {k:v for k, v in ct.Counter(lst).items() if v > 1}
missing = (i for i, _ in enumerate(lst) if i not in set(lst))
for i in excluded_indices():
lst[i] = next(missing)
return lst
台阶
lst
中查找所有重复元素的值(k
)和频率(v
)lst
大小成比例的范围内的所有缺失数字排除的\u索引
-重复的元素的索引(每个重复的
值的最终出现除外)
缺失的编号覆盖lst
中的元素
def locate(iterable, pred=bool):
return it.compress(it.count(), map(pred, iterable))
您需要分两个阶段来完成这项工作(或者让其他人分两个阶段来完成)——首先找到缺少的值,然后浏览列表,用缺少的值替换重复的值。比如:
def normalize_list(data):
# data = list(data) # uncomment if you don't want to modify the source list
# use xrange() instead of range() on Python 2.x
missing_keys = [i for i in range(len(data)-1, -1, -1) if i not in set(data)]
for index, value in enumerate(data):
try:
if data.index(value, index+1):
data[index] = missing_keys.pop()
except ValueError:
pass
return data
print(normalize_list([0, 1, 6, 7, 5, 4, 3, 2, 1]))
# prints: [0, 8, 6, 7, 5, 4, 3, 2, 1]
print(normalize_list([0, 1, 2, 7, 3, 4, 3, 2, 1]))
# prints: [0, 5, 6, 7, 8, 4, 3, 2, 1]
这应该适用于任何大小的列表
更新
考虑到list.index()
的缓慢性,这里有一个没有它的版本-它看起来有点不直观(多了一个循环),但是它比第一个示例快了近4倍(列表越长,相对于第一个示例,它的速度就越快),并且内存使用稍微多一些:
def normalize_list(data):
# data = list(data) # uncomment if you don't want to modify the source list
key_lookup = dict.fromkeys(data, -1)
# use xrange() instead of range() on Python 2.x
missing_keys = [i for i in range(len(data)-1, -1, -1) if i not in key_lookup]
for i in data:
key_lookup[i] += 1
for index, value in enumerate(data):
try:
if key_lookup[value]:
data[index] = missing_keys.pop()
key_lookup[value] -= 1
except ValueError:
pass
return data
以下是另一种方法:
顺序重要吗?请展示您的尝试。您听说过
集合
类吗?列表中的元素数是否始终与最大值相同?如果存在多个重复,会发生什么情况?是否始终要替换第一个或最后一个元素?我的观点是,这是一个非常不明确的问题,你应该在提问之前对你的问题进行更多的思考。如果您花时间精确地说明需求,您可能会自己想出一个答案。这些需求没有正确地指定。请添加更多详细信息。为什么要在每个循环中重建缺失的列表?听起来很低效。另外,与列表生成相反,list.pop()
要比list.pop(0)
快得多。哎呀,缺失
不属于循环,好的捕获方法非常有趣。。。效率很低,需要安装额外的模块,tho…@zwer谢谢您的评论。我为那些对pip安装more\u itertools
不感兴趣的人添加了实现,因此它不依赖于任何安装。至于效率,我相信你的例子不会更快,尽管这是一个有趣的变化。因此,我不确定你的意思。相当低效==将以非最佳方式运行。此外,它不会产生期望的输出-第一个输出大约是唯一一个符合OP要求的输出。仍然有点模糊,但我改进了您发现的清晰点。谢谢
def normalize_list(data):
# data = list(data) # uncomment if you don't want to modify the source list
key_lookup = dict.fromkeys(data, -1)
# use xrange() instead of range() on Python 2.x
missing_keys = [i for i in range(len(data)-1, -1, -1) if i not in key_lookup]
for i in data:
key_lookup[i] += 1
for index, value in enumerate(data):
try:
if key_lookup[value]:
data[index] = missing_keys.pop()
key_lookup[value] -= 1
except ValueError:
pass
return data
xs = [0, 1, 6, 7, 5, 4, 3, 2, 1]
fixed = {x: i for i, x in enumerate(xs)}
spares = iter(x for x in range(len(xs)) if x not in fixed)
res = [x if i == fixed[x] else next(spares)
for i, x in enumerate(xs)]
def returnModifiedList(x):
#find indices where there is a repeat
storage=[]; indices = []
for i in range(len(x)-1,-1,-1):
if x[i] in storage:
indices.append(i)
else:
storage.append(x[i])
#find values that are missing
s = sorted(list(set(x)))
missing = list(reversed([i for i in range(len(x)) if (i not in s)]))
#fill in repeats with missing values
for i in range(len(indices)):
x[indices[i]] = missing[i]
return x
x = [0, 1, 2, 7, 3, 4, 3, 2, 1]
results = returnModifiedList(x)
print results