Python 列表中的第n个重复元素
我对以下解决方案的更具pythonic和performant的方法感兴趣Python 列表中的第n个重复元素,python,list,repeat,Python,List,Repeat,我对以下解决方案的更具pythonic和performant的方法感兴趣 def nthFrequent(arr,n): d = dict((x, arr.count(x)) for x in set(arr)) value = sorted(d.values(), reverse=True) # Pick nth repeated element nthrepeat = value[n-1] for (key, val) in d.iteritem
def nthFrequent(arr,n):
d = dict((x, arr.count(x)) for x in set(arr))
value = sorted(d.values(), reverse=True)
# Pick nth repeated element
nthrepeat = value[n-1]
for (key, val) in d.iteritems():
if val == nthrepeat:
return key
a=[1,2,3,4,5,6,7,92,3,2,35,9,2,43,4,9,9,9]
print nthFrequent(a,2)
上述代码将返回2,因为2在9之后重复3次,即4次
我正在寻找更优雅的使用lambda的方法,我尝试了以下方法,但没有得到所需的结果
set(a)中项目的最大值((项目,a.count(项目)),key=lambda k:k[1])[0]
上面的一个将得到最大重复值,即9
如何获得第二个或第N个?如果您正在寻找单行程序,以下操作应该可以:
返回集合(a)中项目的排序((项目,a.count(项目)),key=lambda k:k[1],reverse=True)[n-1][0]
虽然上面使用了更多的Python语言特性,但实际上我更喜欢原始代码的可读性
作为旁注,在原始代码中,您应该returnkey
,因为您当前正试图打印一个不返回值的函数
如@sberry所述,如果您关心领带,您可以:
当计数相同时获取最小值:
return sorted(((item, a.count(item)) for item in set(a)),
key=lambda k: (k[1], k[0]), reverse=True)[n-1][0]
return sorted(((item, a.count(item)) for item in set(a)),
key=lambda k: (k[1], -k[0]), reverse=True)[n-1][0]
计数相同时获取最大值:
return sorted(((item, a.count(item)) for item in set(a)),
key=lambda k: (k[1], k[0]), reverse=True)[n-1][0]
return sorted(((item, a.count(item)) for item in set(a)),
key=lambda k: (k[1], -k[0]), reverse=True)[n-1][0]
这对于collections.Counter来说是非常直接的。但是,请注意,如果
n
值更改为3,此解决方案将只返回3或4中的一个,因为在这种情况下会出现平局
import collections
def nthFrequent(arr,n):
return sorted([(v, k) for k, v in collections.Counter(arr).items()], reverse=True)[n-1][1]
a = [1,2,3,4,5,6,7,92,3,2,35,9,2,43,4,9,9,9]
print nthFrequent(a,2)
还值得注意的是:元组列表按元组的0索引元素排序。因此,您可以将元组与(count,value)
一起使用,然后只返回该值。排序中不需要lambda
如果您确实希望在不导入的情况下执行此操作,那么即使是这样,也将是一个更快的实现:
def nthFrequent3(arr, n):
d = {}
for v in arr:
if v not in d:
d[v] = 0
d[v] += 1
return sorted([(v, k) for k, v in d.items()], reverse=True)[n-1][1]
如果您将来决定使用导入,那么也可以看看itertools。它还有一些方便的工具
def nthFrequent2(arr, n):
for i, (value, _) in enumerate(itertools.groupby(sorted(arr))):
if i == n - 1:
return value
设N为arr
的长度,此行:
d = dict((x, arr.count(x)) for x in set(arr))
按照N2的顺序进行许多步骤。首先,遍历arr
以找到其唯一的元素(最坏的情况是每个元素都是唯一的)。其次,对于每个唯一的元素,再次遍历整个列表以计算该元素出现的次数。单线溶液的数量级也为N2
这是许多不必要的重复步骤。您只需查看arr
的每个元素一次。在一个步骤中,您可以:
- 检查您是否已经看到此元素
- 增加此元素的计数器
counter = {}
for x in arr:
if x not in counter:
counter[x] = 0
counter[x] += 1
pairs = sorted(counter.iteritems(), key=lambda pair: pair[1], reverse=True)
key, count = pairs[n]
return key
在最坏的情况下,每个元素都是唯一的,由于排序的原因,该代码按N*log(N)的顺序执行了许多步骤。(传递的
arr
顺序为N,因为Python中的dict
查找顺序为1。)您能提供一个示例输入和预期输出吗?不确定您想在这里用lambda做什么,但是,如果您只想找到一个重复N次的元素,最好使用计数器
或手动计算出现次数(不调用计数
)。您当前的解决方案是O(N^2),但您可以在O(N)中解决此问题。谢谢@sberry。我的意图是尽量避免收集,你有什么具体的原因吗?你要求的是更具“python和performant”的东西,这两者都是。当然,这是performant和python。但是,我没有使用任何模块导入来查找某些内容。谢谢你给我带来的痛苦和解释。@paddu我很想知道你为什么不使用导入就这样做?我的意思是,它们是标准库的一部分是有原因的。@paddu,如果你担心污染名称空间,你可以只导入你需要的一个函数:从集合导入计数器
谢谢,return是我在lambda和原始代码之间尝试时弄糟的东西。计数器[x]=Counter.get(x,0)+1
避免需要if条件。