arrays - using python itertools to manage nested for loops -
i trying use itertools.product manage bookkeeping of nested loops, number of nested loops not known in advance. below specific example have chosen 2 nested loops; choice of 2 clarity, need solution works arbitrary number of loops.
this question provides extension/generalization of question appearing here: efficient algorithm evaluating 1-d array of functions on same-length 1d numpy array
now extending above technique using itertools trick learned here: iterating on unknown number of nested loops in python
preamble:
from itertools import product def trivial_functional(i, j): return lambda x : (i+j)*x idx1 = [1, 2, 3, 4] idx2 = [5, 6, 7] joint = [idx1, idx2] func_table = [] items in product(*joint): f = trivial_functional(*items) func_table.append(f)
at end of above itertools loop, have 12-element, 1-d array of functions, func_table, each element having been built trivial_functional.
question:
suppose given pair of integers, (i_1, i_2), these integers interpreted indices of idx1 , idx2, respectively. how can use itertools.product determine correct corresponding element of func_table array?
i know how hack answer writing own function mimics itertools.product bookkeeping, surely there built-in feature of itertools.product intended purpose?
i don't know of way of calculating flat index other doing yourself. fortunately isn't difficult:
def product_flat_index(factors, indices): if len(factors) == 1: return indices[0] else: return indices[0] * len(factors[0]) + product_flat_index(factors[1:], indices[1:]) >> product_flat_index(joint, (2, 1)) 9
an alternative approach store results in nested array in first place, making translation unnecessary, though more complex:
from functools import reduce operator import getitem, setitem, itemgetter def get_items(container, indices): return reduce(getitem, indices, container) def set_items(container, indices, value): c = reduce(getitem, indices[:-1], container) setitem(c, indices[-1], value) def initialize_table(lengths): if len(lengths) == 1: return [0] * lengths[0] subtable = initialize_table(lengths[1:]) return [subtable[:] _ in range(lengths[0])] func_table = initialize_table(list(map(len, joint))) items in product(*map(enumerate, joint)): f = trivial_functional(*map(itemgetter(1), items)) set_items(func_table, list(map(itemgetter(0), items)), f) >>> get_items(func_table, (2, 1)) # same func_table[2][1] <function>
Comments
Post a Comment