[英]what's the fastest way to sort/filter/sum increasing digits of numbers in a list
例:
L = [12,14,22,41,21,23]
我希望结果是:
R == [12,14,22,23]
数字的位数必须按升序排列,以下是我的解决方法,它们都可以工作,但是它们都太慢了。
最快的排序方式是什么?
解决方法一:
R = filter(lambda j: int(''.join(sorted(str(j))))==j , L)
解决方法二:
for j in L:
if int(''.join(sorted(str(j))))==j:
R.append(j)
问题2-另外,我希望将这些对应的数字加起来等于5。
这是我的解决方案,同样,它们确实有效,但是速度太慢。
那么最快的方法是什么。
newR_should_be == [14,23]
一:
newR = filter(lambda i: sum([int(x) for x in str(i)])==5 ,R)
二:
for i in R:
if sum([int(x) for x in str(i)])==5:
newR.append(i)
任何帮助,将不胜感激。
OlivierMelançon解决方案非常优雅。 但是,如果您愿意编写难看的代码,则可以避免字符串转换并同时执行两个测试,从而使其运行得更快。 我实现了您的解决方案ast1,OlivierMelançon实现为t2,我的实现为t3。
def FastFilter(n):
x = n % 10
s = x
n //= 10
while n:
y = n % 10
s += y
if (x < y):
return False
x = y;
n //= 10
return s==5
def sort_by_digits(l):
return sorted(set(int(''.join(sorted(str(x)))) for x in l))
def filter_by_sum(l, total=5):
return [x for x in map(str, l) if sum(map(int, x)) == total]
def t1(L):
R = filter(lambda j: int(''.join(sorted(str(j))))==j , L)
newR = filter(lambda i: sum([int(x) for x in str(i)])==5 ,R)
return sorted(newR)
def t2(l):
return sort_by_digits(filter_by_sum(l))
def t3(l):
return sorted(filter(FastFilter, l))
l = [12, 14, 22, 41, 21, 23]
%timeit t1(l)
%timeit t2(l)
%timeit t3(l)
给
11.2 µs ± 24.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
8.88 µs ± 24.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
2.71 µs ± 12.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
如果您尝试使用一种功能性方法(即filter
,则可以尝试以下操作:
L = [12,14,22,41,21,23]
while not all(L[i] <= L[i+1] for i in range(len(L)-1)):
L = map(lambda x:x[-1], filter(lambda x:L[x[0]+1] >= x[-1] if x[0]+1 < len(L) else True, zip(range(len(L)), L)))
print(L)
输出:
[12, 14, 21, 23]
依靠内置的Python通常是最有效的方法。 它也只需要几行代码就可以完成很多工作。
l = [12, 14, 22, 41, 21, 23]
def sort_by_digits(l):
return sorted(set(int(''.join(sorted(str(x)))) for x in l))
sort_by_digits(l) # [12, 14, 21, 23]
至于总和,您可以做类似的事情。
def filter_by_sum(l, total=5):
return [x for x in map(str, l) if sum(map(int, x)) == total]
sort_by_digits(filter_by_sum(l)) # [14, 23]
这是我不喜欢Python的原因之一:您提出的简单解决方案(在大多数语言中都可以很好地工作)可能与Python中的糖蜜一样慢。 高级操作过多。
但是我们可以使用Numpy来解决此问题,如下所示:
#!/usr/bin/env python3
import numpy as np
COUNT = 1000
MAXNUM = 100000
MAXDIGITS = 6
prevremain = 99*np.ones(COUNT) #The previous digit we removed from the RHS
origdata = np.random.randint(0,MAXNUM,size=COUNT) #Original data
quot = origdata.copy() #What's left when we remove a digit from the RHS
good = np.ones(COUNT) #Whether the number's digits are monotonically decreasing from right to left
for i in range(1,MAXDIGITS): #Pull digits off of the numbers one at a time
quot, remain = np.divmod(quot,10) #quot is the rest of the number, remain is the right-most digit
#Check to see if this digit was smaller, or equal to, than the last one we
#removed. NOTE: If you have numbers with an unequal number of digits, you'll
#need to think carefully about whether `<=` might work better for you.
good = np.logical_and(good, (remain < prevremain))
prevremain = remain
#These are the numbers you want
print(origdata[good])
Numpy将更多的计算卸载到可以快速运行的低级库中。 在这种情况下,它可以使用向量化的数学运算来快速对整个输入进行数字检查。 然后,您可以将它们用作过滤器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.