2016-11-04 43 views
3

這是this question的一種修改,其中我想除了元素本身之外還返回數組元素的索引。我已成功修改arraysums(),arraysums_recursive(),但我正在努力與arraysums_recursive_anyvals()。下面是詳細信息:總結任意數量的數組的所有可能的組合,並應用限制和返回索引

我修改arraysums()

def arraysums(arrays,lower,upper): 
    products = itertools.product(*arrays) 
    result = list() 

    indices = itertools.product(*[np.arange(len(arr)) for arr in arrays]) 
    index = list() 

    for n,k in zip(products,indices): 
     s = sum(n) 
     if lower <= s <= upper: 
      result.append(n) 
      index.append(k)     
    return result,index 

現在返回的元素和元素的索引:

N = 8 
a = np.arange(N) 
b = np.arange(N)-N/2  
arraysums((a,b),lower=5,upper=6) 


([(2, 3), 
    (3, 2), 
    (3, 3), 
    (4, 1), 
    (4, 2), 
    (5, 0), 
    (5, 1), 
    (6, -1), 
    (6, 0), 
    (7, -2), 
    (7, -1)], 
[(2, 7), 
    (3, 6), 
    (3, 7), 
    (4, 5), 
    (4, 6), 
    (5, 4), 
    (5, 5), 
    (6, 3), 
    (6, 4), 
    (7, 2), 
    (7, 3)]) 

我也修改@ unutbu的遞歸解決方案,還返回與arraysums()相同的結果:

def arraysums_recursive(arrays, lower, upper): 
    if len(arrays) <= 1: 
     result = [(item,) for item in arrays[0] if lower <= item <= upper] 
     index = [] # this needs to be fixed 
    else: 
     result = [] 
     index = [] 
     for item in arrays[0]: 
      subarrays = [[item2 for item2 in arr if item2 <= upper-item] 
         for arr in arrays[1:]] 
      result.extend(
       [(item,)+tup for tup in arraysums(
        subarrays, lower-item, upper-item)[0]]) 
      index.extend(
       [(item,)+tup for tup in arraysums(
        subarrays, lower-item, upper-item)[1]]) 

    return result,index 

最後,我修改arraysums_recursive_anyvals(),但我似乎無法理解爲什麼它不返回指數:

def arraysums_recursive_anyvals(arrays, lower, upper): 
    if len(arrays) <= 1: 
     result = [(item,) for item in arrays[0] if lower <= item <= upper] 
     index = [] # this needs to be fixed 
    else: 
     minval = min(item for arr in arrays for item in arr) 
     # Subtract minval from arrays to guarantee all the values are positive 
     arrays = [[item-minval for item in arr] for arr in arrays] 
     # Adjust the lower and upper bounds accordingly 
     lower -= minval*len(arrays) 
     upper -= minval*len(arrays) 

     result = [] 
     index = [] 
     for item in arrays[0]: 
      subarrays = [[item2 for item2 in arr if item2 <= upper-item] 
         for arr in arrays[1:]] 
      if min(len(arr) for arr in subarrays) == 0: 
       continue 
      result.extend(
       [(item,)+tup for tup in arraysums_recursive(
        subarrays, lower-item, upper-item)[0]]) 
      index.extend(
       [(item,)+tup for tup in arraysums_recursive(
        subarrays, lower-item, upper-item)[1]]) 

     # Readjust the result by adding back minval 
     result = [tuple([item+minval for item in tup]) for tup in result] 
    return result,index 

結果:

arraysums_recursive_anyvals((a,b),lower=5,upper=6) 

([(2, 3), 
    (3, 2), 
    (3, 3), 
    (4, 1), 
    (4, 2), 
    (5, 0), 
    (5, 1), 
    (6, -1), 
    (6, 0), 
    (7, -2), 
    (7, -1)], 
[]) 

回答

2

arraysums_recursive一個重要特點是,它拋出值這不可能有助於結果:

subarrays = [[item2 for item2 in arr if item2 <= upper-item] 
       for arr in arrays[1:]] 

雖然拋出事情使指數的記錄變得複雜,但並不難。 首先,在arraysums_recursive擴大arrays爲包括指數以及項目值:

def arraysums_recursive(arrays, lower, upper): 
    arrays = [[(i, item) for i, item in enumerate(arr)] for arr in arrays] 
    ... 
    index, result = zip(*arraysums_recursive_all_positive(arrays, lower, upper)) 
    return result, index 

現在重寫arraysums_recursive_all_positive處理arrays其中包括(index, item)元組列表的列表中。


def arraysums_recursive(arrays, lower, upper): 
    arrays = [[(i, item) for i, item in enumerate(arr)] for arr in arrays] 
    minval = min(item for arr in arrays for i, item in arr) 
    # Subtract minval from arrays to guarantee all the values are positive 
    arrays = [[(i, item-minval) for i, item in arr] for arr in arrays] 
    # Adjust the lower and upper bounds accordingly 
    lower -= minval*len(arrays) 
    upper -= minval*len(arrays) 
    index, result = zip(*arraysums_recursive_all_positive(arrays, lower, upper)) 
    # Readjust the result by adding back minval 
    result = [tuple([item+minval for item in tup]) for tup in result] 
    return result, index 

def arraysums_recursive_all_positive(arrays, lower, upper): 
    # Assumes all values in arrays are positive 
    if len(arrays) <= 1: 
     result = [((i,), (item,)) for i, item in arrays[0] if lower <= item <= upper] 
    else: 
     result = [] 
     for i, item in arrays[0]: 
      subarrays = [[(i, item2) for i, item2 in arr if item2 <= upper-item] 
         for arr in arrays[1:]] 
      if min(len(arr) for arr in subarrays) == 0: 
       continue 
      result.extend(
       [((i,)+i_tup, (item,)+item_tup) for i_tup, item_tup in 
       arraysums_recursive_all_positive(subarrays, lower-item, upper-item)]) 
    return result 

import numpy as np 
N = 8 
a = np.arange(N) 
b = np.arange(N)-N/2  
result, index = arraysums_recursive((a,b),lower=5,upper=6) 

產量result

[(2.0, 3.0), 
(3.0, 2.0), 
(3.0, 3.0), 
(4.0, 1.0), 
(4.0, 2.0), 
(5.0, 0.0), 
(5.0, 1.0), 
(6.0, -1.0), 
(6.0, 0.0), 
(7.0, -2.0), 
(7.0, -1.0)] 

index

((2, 7), 
(3, 6), 
(3, 7), 
(4, 5), 
(4, 6), 
(5, 4), 
(5, 5), 
(6, 3), 
(6, 4), 
(7, 2), 
(7, 3)) 
+0

一個問題是此起彼伏爲t index_maps包含的鍵有輕微的錯誤(可能是一些浮點運算):[{-17.25:11,-21.579999999999998:6,-7.6100000000000003:16,...}]。這會導致KeyError偶爾被拋出。 – justin

+0

好的,好點。在這種情況下,仔細記錄指數(與相應的值配對)可能是最好的方法。我修改了代碼以顯示我的意思。 – unutbu

相關問題