更新:我相信我找到了解决方案。我把它放在最后。
假设我们有以下列表:
a = ['a', 'a', 'b', 'b', 'a', 'a', 'c', 'c']
我想创建另一个列表,以从列表a
中删除重复项,但同时,保持比率不变,并保持顺序。
输出应为:
b = ['a', 'b', 'a', 'c']
编辑:为了更好地解释,该比率不必完全完整。所需要做的就是为数据中的所有字母输出一个单个字母。但是,两个字母可能相同,但是代表了两个不同的事物。正如我稍后所说,计数对于识别这一点很重要。代表一个唯一变量的字母的计数介于3000-3400之间,因此当我将总数除以3500并四舍五入时,我知道最后应该出现多少次,但是问题是我不知道它们应该按什么顺序排列在。
为了说明这一点,我将再添加一个输入和所需的输出:
请注意,“ C”已重复了3次。比率不必精确保留,我只需要表示该变量被表示多少次,并且由于在此示例中该变量仅被表示3次,因此不足以将其计为2。 唯一的区别是,这里我假设所有重复正好重复两次的字母都是唯一的,尽管在数据集中,唯一性还是取决于外观3000-3400次。
注意(1):不一定要考虑这一点,但是有可能并非所有字母都可以很好地分组在一起,例如,考虑4个字母的唯一性以使其简短:['a',' a','b','a','a','b','b','b','b']仍应表示为['a','b']。但是,在这种情况下,这是一个小问题。
编辑: 我尝试并成功完成的示例:
full_list = ['a', 'a', 'b', 'b', 'a', 'a', 'c', 'c']
#full_list is a list containing around 10k items, just using this as example
rep = 2 # number of estimated repetitions for unique item,
# in the real list this was set to 3500
quant = {'a': 0, "b" : 0, "c" : 0, "d" : 0, "e" : 0, "f" : 0, "g": 0}
for x in set(full_list):
quant[x] = round(full_list.count(x)/rep)
final = []
for x in range(len(full_list)):
if full_list[x] in final:
lastindex = len(full_list) - 1 - full_list[::-1].index(full_list[x])
if lastindex == x and final.count(full_list[x]) < quant[full_list[x]]:
final.append(full_list[x])
else:
final.append(full_list[x])
print(final)
我上面的代码有两个问题:
最后一句话:我尝试过的代码更多地是为了在最普通的输入上实现所需的输出,但是并不能完全达到我的预期。同样重要的是要注意输入随时间变化。单个字母的重复并不总是相同的,尽管我相信它们总是组合在一起的,所以我在考虑制作一个标记,该标记在击中一个字母时会变为True,并在更改为另一个字母后立即变为false,但这还有一个问题,就是无法解释两个相同的字母可能会紧挨在一起的事实。每个字母作为一个字母的总计数始终在3000-3400之间,因此我知道,如果该计数超过该数字,则该数量将大于1。
更新:解决方案 遵循hiro主角的建议,并进行了一些修改,以下代码似乎有效:
full = ['a', 'a', 'b', 'b', 'a', 'a', 'c', 'c', 'a', 'a']
from itertools import groupby
letters_pre = [key for key, _group in groupby(full)]
letters_post = []
for x in range(len(letters_pre)):
if x>0 and letters_pre[x] != letters_pre[x-1]:
letters_post.append(letters_pre[x])
if x == 0:
letters_post.append(letters_pre [x])
print(letters_post)
唯一的问题是,它不认为有时字母可以出现在唯一的字母之间,如“ Note(1)”中所述,但这只是一个很小的问题。更大的问题是,例如,同一字母的两个单独出现是连续的(例如,两个以唯一性为例)是不连续的:['a','a','a','a','b当所需的输出应为['a','a','b']
时,','b']变为['a','b']答案 0 :(得分:2)
这是itertools.groupby
派上用场的地方:
from itertools import groupby
a = ["a", "a", "b", "b", "a", "a", "c", "c"]
res = [key for key, _group in groupby(a)]
print(res) # ['a', 'b', 'a', 'c']
这是一个您可以“缩小”唯一键的版本(但保证结果中至少有一个):
from itertools import groupby, repeat, chain
a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'a', 'a',
'd', 'd', 'a', 'a']
scale = 0.4
key_count = tuple((key, sum(1 for _item in group)) for key, group in groupby(a))
# (('a', 4), ('b', 2), ('c', 5), ('a', 2), ('d', 2), ('a', 2))
res = tuple(
chain.from_iterable(
(repeat(key, round(scale * count) or 1)) for key, count in key_count
)
)
# ('a', 'a', 'b', 'c', 'c', 'a', 'd', 'a')
可能有更聪明的方法来确定scale
(可能基于输入列表a
的长度和平均group
的长度)。
答案 1 :(得分:1)
可能是一个奇怪的人,但是:
b = []
for i in a:
if next(iter(b[::-1]), None) != i:
b.append(i)
print(b)
输出:
['a', 'b', 'a', 'c']