繁体   English   中英

排序/过滤/求和列表中递增数字的最快方法是什么

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM