有没有更好的方法可以同时解析两个列表?

时间:2019-03-19 10:05:14

标签: python-3.x numpy

我试图猜测两个巨大列表中两个数字的完美组合。

for x in list_a:
    for y in list_b:
        if round((x * 0.24 + y * 0.13), 2) == value:
            print('success')

这花费了很多时间,因为我的列表的len超过600。我的第一个想法是将庞大的列表拆分为较小的列表并检查结果。例如,如果x和y的等式<=值-4移动到下一个列表的集合,直到x和y ==值。

1)如何将列表分成较小的集群? 2)如何有效地更改集? 3)有没有办法避免嵌套循环?

2 个答案:

答案 0 :(得分:2)

我不太确定要尝试找到哪个最佳条件,但是如果您想在没有两个for循环的情况下重现以上计算,则可能会有所帮助。尝试计算一个numpy数组中的所有值:

arr = np.around(np.outer(0.24 * np.array(list_A), 0.13 * np.array(list_B)),2)

它将返回一个矩阵,该矩阵存储您正在for循环中计算的所有值,并且您可以获得一个布尔矩阵,该矩阵表明A和B的哪对满足条件

boolian_arr = arr == value

(此解决方案不包含任何奇特的搜索算法,只是使用numpy的两个慢速for循环的替代方法。)

答案 1 :(得分:2)

更新(澄清问题):

无需猜测,因为您可以精确求解(最多为数字):

M = np.array([[1, 1], [0.24, 0.13]])
high_taxed, low_taxed = np.linalg.solve(M, [Start_Value, Tax])

更新结束。

您可以使用以下技巧来获得O(n + m log n + m)运行时。

  1. 通过系数0.24和0.13缩放列表a和b
  2. 用v-b替换b
  3. 恰恰是当a_i接近(v-b)_j时a_i + b_j接近v
  4. 牢记这一点,将a和v-b组合在一起,进行排序,并求出并非来自同一子集的所有相邻元素之间的差异
  5. 在diff中找到最小的元素。这对应于最佳匹配

import numpy as np

def closest_match(a, b, v, fa=24, fb=13, fv=100):
    ab = np.concatenate([fa*a, fv*v - fb*b])
    idx = ab.argsort(kind='stable')
    ina = idx<len(a)
    swtch, = np.where(ina[1:]^ina[:-1])
    mm = np.diff(ab[idx])[swtch]
    abidx = swtch[np.argmin(np.abs(mm))]
    aidx, bidx = sorted(idx[abidx:abidx+2])
    bidx -= len(a)
    return aidx, bidx

示例:

a = np.arange(-10, 10000, 7)
b = np.arange(20, 4000, 3)
v = 99
closest_match(a, b, v)
#(1, 249)
a[1]*24 + b[249]*13
#9899
v*100
#9900

# best match is one off
# validate using brute force

np.abs(np.add.outer(a*24, b*13)-v*100).min()
#1

# yep, one is as good as it gets

与蛮力相比的计时

timeit(lambda: np.unravel_index(np.abs(np.add.outer(a*24, b*13)-v*100).argmin(), (len(a), len(b))), number=1000)
#17.82432043197332
timeit(lambda: closest_match(a, b, v), number=1000)
#0.11731306000729091

提速超过100倍。