Python 在列表中查找要进行总和优化的值
这确实是我今年早些时候问过的一个问题的后续问题。对于以下问题,我得到了一个很好的答案: 我正试着编写一些简单的Python代码来识别 列表中的值的组合,其总和为定义值, 在一定范围内 例如: 如果A=[0.4,2,3,1.4,2.6,6.3]且目标值为5+/-0.5,则 我想要的输出是(2,3),(1.4,2.6),(2,2.6),(0.4,2,3),(0.4,3,1.4) 等。如果未找到组合,则函数应返回0或 没有或类似的东西 我在代码中实现了这个建议。然而,该方法(见下文)很快成为我代码中的性能限制步骤。运行每个迭代相当快,但它被运行了很多次 因此,我要把这件事告诉社区(他们比我聪明得多),感谢你们的帮助。你能看到如何优化这个功能或者用更快的东西来代替它吗Python 在列表中查找要进行总和优化的值,python,algorithm,python-2.7,optimization,Python,Algorithm,Python 2.7,Optimization,这确实是我今年早些时候问过的一个问题的后续问题。对于以下问题,我得到了一个很好的答案: 我正试着编写一些简单的Python代码来识别 列表中的值的组合,其总和为定义值, 在一定范围内 例如: 如果A=[0.4,2,3,1.4,2.6,6.3]且目标值为5+/-0.5,则 我想要的输出是(2,3),(1.4,2.6),(2,2.6),(0.4,2,3),(0.4,3,1.4) 等。如果未找到组合,则函数应返回0或 没有或类似的东西 我在代码中实现了这个建议。然而,该方法(见下文)很快成为我代码中的
def findSum(self, dataArray, target, tolerance=0.5):
for i in xrange(1, len(dataArray)+1):
results = [list(comb) for comb in list(itertools.combinations(dataArray, i))
if target-tolerance < sum(map(float, comb)) < target+tolerance]
if len(results) != 0:
return results
def findSum(自身、数据阵列、目标、公差=0.5):
对于X范围内的i(1,len(数据阵列)+1):
结果=[列表中的梳的列表(梳)(itertools.compositions(dataArray,i))
如果目标公差<总和(映射(浮点、梳状))<目标+公差]
如果len(结果)!=0:
返回结果
这似乎是最重要的
根据维基百科,如果A中的所有元素都是正数,并且您搜索的是近似结果,则此算法:
initialize a list S to contain one element 0.
for each i from 1 to N do
let T be a list consisting of xi + y, for all y in S
let U be the union of T and S
sort U
make S empty
let y be the smallest element of U
add y to S
for each element z of U in increasing order do
//trim the list by eliminating numbers close to one another
//and throw out elements greater than s
if y + cs/N < z ≤ s, set y = z and add z to S
if S contains a number between (1 − c)s and s, output yes, otherwise no
初始化列表以包含一个元素0。
对于每个i,从1到N do
让T是由席+y组成的列表,用于所有y中的y
让你成为T和S的结合体
排序U
空的
设y为U的最小元素
加y到S
对于U的每个元素z,按递增顺序do
//通过删除彼此接近的数字来修剪列表
//并抛出大于s的元素
如果y+cs/N
我应该给你答案。它具有多项式复杂性
在伪python中(很抱歉,我有一段时间没有编写python了)
def计算(A、s、c):
'''
A是包含您的号码的列表
s是你的目标值
c是你的近似值,即+/-0.5
'''
S=[0]
y=0
对于x范围内的i(1,N):
T=[x+y代表A中的x代表S中的y]
U=列表(集合(T)|集合(S))
U.sort()
S=[]
y=最小值(U)
S=[y]
对于U中的z:
如果y+cs/N return[x for x in S,x>S-c,x我在前面的问题中提供了递归函数的答案,并为此答案对其进行了一些优化。它不仅比使用itertools.combines()
更快,而且还返回了正确的答案
import itertools
import timeit
def findSum(dataArray, target, tolerance=0.5):
for i in xrange(1, len(dataArray)+1):
results = [list(comb) for comb in list(itertools.combinations(dataArray, i))
if target-tolerance <= sum(map(float, comb)) <= target+tolerance]
if len(results) != 0:
return results
def recursive(dataArray, target, tolerance=0.5, i=0, possible=[]):
results = []
max_target = target + tolerance
min_target = target - tolerance
l = len(dataArray)
while i < l:
a = dataArray[i]
i += 1
if a > max_target: # possible+[a] is too large
break
if a >= min_target: # Found a set that works
results.append(possible+[a])
# recursively try with a shortened list dataArray and a reduced target
result = recursive(dataArray, target-a, tolerance, i, possible+[a])
if result: results += result
return results
dataArray = [0.4,2,3,1.4,2.6,6.3]
dataArray.sort()
target = 5
print findSum(dataArray, target)
print recursive(dataArray, target)
print timeit.Timer(lambda: findSum(dataArray, target)).timeit(number=100000)
print timeit.Timer(lambda: recursive(dataArray, target)).timeit(number=100000)
根据数据的不同,递归函数可能更快,因为当排序的数据不再适合目标范围时,它会退出一个循环。这要求在调用函数之前对dataArray
进行排序。将是一个更好的位置。根据我的理解,是决策变量的数量,是您尝试求和的列表。(python伪代码中的A列表)cs我不太确定,我复制它太快了,我没有注意到。我猜它可能是c*s(c的一个小常量>0,你的目标值是多少)?我会研究它
import itertools
import timeit
def findSum(dataArray, target, tolerance=0.5):
for i in xrange(1, len(dataArray)+1):
results = [list(comb) for comb in list(itertools.combinations(dataArray, i))
if target-tolerance <= sum(map(float, comb)) <= target+tolerance]
if len(results) != 0:
return results
def recursive(dataArray, target, tolerance=0.5, i=0, possible=[]):
results = []
max_target = target + tolerance
min_target = target - tolerance
l = len(dataArray)
while i < l:
a = dataArray[i]
i += 1
if a > max_target: # possible+[a] is too large
break
if a >= min_target: # Found a set that works
results.append(possible+[a])
# recursively try with a shortened list dataArray and a reduced target
result = recursive(dataArray, target-a, tolerance, i, possible+[a])
if result: results += result
return results
dataArray = [0.4,2,3,1.4,2.6,6.3]
dataArray.sort()
target = 5
print findSum(dataArray, target)
print recursive(dataArray, target)
print timeit.Timer(lambda: findSum(dataArray, target)).timeit(number=100000)
print timeit.Timer(lambda: recursive(dataArray, target)).timeit(number=100000)
[[2, 2.6], [2, 3]]
[[0.4, 1.4, 3], [0.4, 2, 2.6], [0.4, 2, 3], [2, 2.6], [2, 3]]
2.03791809082
1.84496808052