soword科技言
永久公益免费API接口
提供永久免费的API接口,查看更多API接口,如果您有其他免费API资源,请联系我们,造福人类。
提供商务开发:小程序,系统,APP
定制开发,免费评估,免费咨询,价格便宜,售后保障,前往开发服务中心联系开发客服中心
删除列表中一半重复项的有效方法

如果我有一个列表说,l=[1,8,8,8,1,3,3,8]并且可以确保每个元素出现偶数次,那么我该如何列出l当前发生n/2时间的所有元素因此,由于1发生了2几次,所以现在应该发生一次。由于8发生了4多次,因此现在应该发生两次。由于3发生了两次,因此应该发生一次。

因此,新列表将类似于 k=[1,8,8,3]

最快的方法是什么?list.count()为每个元素都做了,但是非常慢。

如果顺序不重要,则一种方法是仅在排序后才获得奇数或偶数索引。这些列表将相同,因此您只需要其中之一。

l = [1,8,8,8,1,3,3,8]l.sort()# Get all odd indexesodd = l[1::2]# Get all even indexeseven = l[::2]print(odd)print(odd == even)

结果:

[1, 3, 8, 8]True

使用计数器来跟踪每个元素的计数

from collections import Counterl = [1,8,8,8,1,3,3,8]res = []count = Counter(l) # its like dict(1: 2, 8: 4, 3: 2)for key, val in count.items():
res.extend(val//2 * [key])print(res)# output[1, 8, 8, 3]

由于您保证列表的每个元素都是2的倍数,因此在构建输出列表时构建计数器要比在先构建计数器(或排序)然后再使用它更快。

l = [1,8,8,8,1,3,3,8]count={}res=[]for i in l:
if i in count: count[i]+=1
else: count[i]=1
if count[i]%2: res.append(i)print(res)

输出量

[1,8,8,3]

编辑比较每种方法的时间/费用

使用该timeit模块表明,此方法比首先使用计数器快2.7倍。

def one():
l = [1,8,8,8,1,3,3,8]
count={}
res=[]
for i in l:
if i in count: count[i]+=1
else: count[i]=1
if count[i]%2: res.append(i)

#print(res)def two():
from collections import Counter
l = [1,8,8,8,1,3,3,8]
res = []
count = Counter(l) # its like dict(1: 2, 8: 4, 3: 2)
for key, val in count.items():
res.extend(val//2 * [key])o=timeit.Timer(one)t=timeit.Timer(two)print(o.timeit(100000))print(t.timeit(100000))print(o.timeit(100000))print(t.timeit(100000))

输出(秒)

0.286660.808220.286780.80113

如果顺序不重要,则最好使用Wimanicesir的方法,将其速度提高4倍,结果为0.07037(比使用反方法快11倍)。

更新 我怀疑Countertwo(无序)中使用该方法可能会导致明显的膨胀或导入速度减慢,因此我测试了“先计数,后编译结果”方法,同时从此处one(有序)使用简单方法进行计数

count={}for i in l:
if i in count: count[i]+=1
else: count[i]=1

这比快得多Counter更换Countertwo测试的定义导致了0.31,而不是0.80的时间。与一样two在计数过程中编译(排序)结果的速度仍然稍快一些对于无序结果,使用Wimanicesir的方法要快得多。

如果您不关心保留相对顺序,则可以先使用来获取每个元素的计数collections.Counter,然后创建一个新列表,每个元素重复一半的次数。

>>> from collections import Counter>>> from itertools import chain>>> list(chain.from_iterable([key]*(count//2) for key, count in Counter(l).items()))[1, 8, 8, 3]

代替使用为列表的每个可能元素跟踪整数的计数器,请尝试使用字典将元素映射到布尔值。第一次看到它们时将其映射为true,然后在每次翻转位时将其映射为真,如果为true,则跳过该元素。

也许这个。

newList = []
for number in l:
if(newList.count(number) < l.count(number)/2):
newList.append(number)print(newList)

会保留一次访问次数不均的所有项目的列表。然后您遍历所有列表项。

在其他语言中,可能会使用一些map()或filter()方法,但这是一些简单的代码,因为我对python的了解不够!:)

l = [1,8,8,8,1,3,3,8]seen = []result = []for num in l:
if num in seen:
seen.remove(num)
#result.append(num) #print every even appearance
else:
seen.append(num)
result.append(num) #print every odd appearanceif len(seen)==0:
print(result)else:
print("Error: uneven elements found:", seen)

最后,受访数组应该为空,因此您可以在返回结果数组之前将其用作完整性检查。

编辑:这是带有过滤器的版本,可返回奇数外观

l = [1,8,8,8,1,3,3,8]seen = []result = list(filter(lambda x: seen.append(x) is None if x not in seen else not seen.remove(x) is None, l))if len(seen)==0:
print(result)else:
print("Error: uneven elements found:", seen)

而这个返回偶数出现:

l = [1,8,8,8,1,3,3,8]seen = []result = list(filter(lambda x: seen.remove(x) is None if x in seen else not seen.append(x) is None, l))if len(seen)==0:
print(result)else:
print("Error: uneven elements found:", seen)



2023-03-22 10:04:19

新人小程序+APP定制199元起


发放福利,助力中小企业发展,真正在互联网中受益

点击询问定制

广告服务展示