Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在列表中查找要进行总和优化的值_Python_Algorithm_Python 2.7_Optimization - Fatal编程技术网

Python 在列表中查找要进行总和优化的值

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或 没有或类似的东西 我在代码中实现了这个建议。然而,该方法(见下文)很快成为我代码中的

这确实是我今年早些时候问过的一个问题的后续问题。对于以下问题,我得到了一个很好的答案:

我正试着编写一些简单的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/Nreturn[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