如何创建一个可以遍历数组中项目内任意数量的函数的函数?

时间:2017-07-29 20:24:29

标签: python arrays loops group-by introspection

我有下面的函数function_iterate_over_array,它接受一个数组和一个函数名列表。虽然该函数确实有效,但我需要创建一个实现相同结果但可以接受任意数量的function_names的函数。

例如,以下函数必须包含四个函数名称

from operator import itemgetter
from itertools import groupby
from dictionary_functions import DictionaryFunctions

group_func = lambda iterable,key:  [list(group) for key, group in groupby(sorted(iterable, key=itemgetter(key)), itemgetter(key))]

def add_one(i):
    return i + 1
def subtract_one(i):
    return i - 1


array = [{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one},
{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one},
{'f1':subtract_one,'f2':subtract_one,'f3':subtract_one,'f4':subtract_one},
{'f1':subtract_one,'f2':add_one,'f3':add_one,'f4':add_one}]

functions = ['f1','f2','f3','f4']

def function_iterate_over_array(array,functions,starting_value=0):
    L = []
    function_key_name = functions[0]
    grouped_array = group_func(array,function_key_name)
    for grouped_array_item in grouped_array:
        function_one = grouped_array_item[0][function_key_name]
        function_one_result = function_one(starting_value)

        function_two_name = functions[1]
        sub_grouped_array = group_func(grouped_array_item,function_two_name)
        for sub_grouped_array_item in sub_grouped_array:
            function_two = sub_grouped_array_item[0][function_two_name]
            function_two_result = function_two(function_one_result)


            function_three_name = functions[2]
            sub_sub_grouped_array = group_func(sub_grouped_array_item,function_three_name)
            for sub_sub_grouped_array_item in sub_sub_grouped_array:
                function_three = sub_sub_grouped_array_item[0][function_three_name]
                function_three_result = function_three(function_two_result)


                function_four_name = functions[3]
                sub_sub_sub_grouped_array = group_func(sub_sub_grouped_array_item,function_four_name)
                for sub_sub_sub_grouped_array_item in sub_sub_sub_grouped_array:
                    function_four = sub_sub_sub_grouped_array_item[0][function_four_name]
                    function_four_result = function_four(function_three_result)


                    for dictionary_from_array in sub_sub_sub_grouped_array_item:
                        D = dict(dictionary_from_array.items()+{'result':function_four_result}.items())
                        L.append(D)

    return L 



L = function_iterate_over_array(array,functions)
#-->[{'f1': <function add_one at 0x1006d5cf8>, 'f2': <function add_one at 0x1006d5cf8>, 'f3': <function add_one at 0x1006d5cf8>, 'f4': <function add_one at 0x1006d5cf8>, 'result': 4}, {'f1': <function add_one at 0x1006d5cf8>, 'f2': <function add_one at 0x1006d5cf8>, 'f3': <function add_one at 0x1006d5cf8>, 'f4': <function add_one at 0x1006d5cf8>, 'result': 4}, {'f1': <function subtract_one at 0x100763ed8>, 'f2': <function add_one at 0x1006d5cf8>, 'f3': <function add_one at 0x1006d5cf8>, 'f4': <function add_one at 0x1006d5cf8>, 'result': 2}, {'f1': <function subtract_one at 0x100763ed8>, 'f2': <function subtract_one at 0x100763ed8>, 'f3': <function subtract_one at 0x100763ed8>, 'f4': <function subtract_one at 0x100763ed8>, 'result': -4}]

我希望用比function_iterate_over_array更好的函数来获得相同的结果,它可以使用任意数量的函数。例如,我希望以下工作:

array = [{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one},
{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one},
{'f1':subtract_one,'f2':subtract_one,'f3':subtract_one,'f4':subtract_one},
{'f1':subtract_one,'f2':add_one,'f3':add_one,'f4':add_one}]
function_iterate_over_array(array,['f1','f2'])

function_iterate_over_array(array,[&#39; f1&#39;,&#39; f2&#39;])应返回以下内容:

[{'f1': <function add_one at 0x101a0fcf8>, 'f2': <function add_one at 0x101a0fcf8>, 'f3': <function add_one at 0x101a0fcf8>, 'f4': <function add_one at 0x101a0fcf8>, 'f5': <function add_one at 0x101a0fcf8>, 'result': 2}, {'f1': <function add_one at 0x101a0fcf8>, 'f2': <function add_one at 0x101a0fcf8>, 'f3': <function add_one at 0x101a0fcf8>, 'f4': <function add_one at 0x101a0fcf8>, 'f5': <function add_one at 0x101a0fcf8>, 'result': 2}]

我通过将function_iterate_over_array更改为以下内容来实现:

def function_iterate_over_array(array,functions,starting_value=0):
    L = []
    function_key_name = functions[0]
    grouped_array = group_func(array,function_key_name)
    for grouped_array_item in grouped_array:
        function_one = grouped_array_item[0][function_key_name]
        function_one_result = function_one(starting_value)

        function_two_name = functions[1]
        sub_grouped_array = group_func(grouped_array_item,function_two_name)
        for sub_grouped_array_item in sub_grouped_array:
            function_two = sub_grouped_array_item[0][function_two_name]
            function_two_result = function_two(function_one_result)


            for dictionary_from_array in sub_grouped_array_item:
                D = dict(dictionary_from_array.items()+{'result':function_two_result}.items())
                L.append(D)
    return L 

我也希望以下工作

array = [{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one,'f5':add_one},
{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one,'f5':add_one}]
functions = ['f1','f2','f3','f4','f5']
function_iterate_over_array(array,functions)

特别是我正在寻找一种更好的方法来编写上述函数,以便它可以接受任意数量的函数。

2 个答案:

答案 0 :(得分:3)

看起来reduce可以帮到你很多。

  

将两个参数的函数累加到iterable的项中,   从左到右,以便将迭代减少到单个值。   例如,reduce(lambda x,y:x + y,[1,2,3,4,5])计算   ((((1 + 2)3)4)5)。左参数x是累计值和   正确的参数y是迭代的更新值。如果   可选的初始化程序存在,它放在项目之前   在计算中可迭代,并在迭代时用作默认值   是空的。如果没有给出初始化器,并且iterable只包含一个   item,返回第一个项目。

它专门设计用于将函数反复应用于值集合。使用lambda,您可以在每一步使用不同的功能。

from functools import reduce

def add_one(i):
    return i + 1

def subtract_one(i):
    return i - 1

function_dicts = [{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one},
{'f1':subtract_one,'f2':subtract_one,'f3':subtract_one,'f4':subtract_one},
{'f1':subtract_one,'f2':add_one,'f3':add_one,'f4':add_one}]

functions = ['f1','f2','f3','f4']

for function_dict in function_dicts:
    result = reduce((lambda value, fname : function_dict[fname](value)), functions, 0)
    print(result)
# 4 
# -4
# 2

它不会返回与您的问题完全相同的格式,但这会提供所需的核心功能。

答案 1 :(得分:2)

虽然排序不同,但这似乎非常接近。我无法按照那种应该做的那样。如果你需要帮助恢复,你能解释那里的目标吗? (请注意,在Python 3中,您的排序甚至不起作用,因为函数不可排序。)

import pprint

def add_one(i):
    return i + 1
def subtract_one(i):
    return i - 1

function_dictionaries = [
    {'f1': add_one, 'f2': add_one, 'f3': add_one, 'f4': add_one},
    {'f1': add_one, 'f2': add_one, 'f3': add_one, 'f4': add_one},
    {'f1': subtract_one, 'f2': subtract_one, 'f3': subtract_one, 'f4': subtract_one},
    {'f1': subtract_one, 'f2': add_one, 'f3': add_one, 'f4': add_one}
]

def apply_functions(function_dictionaries, function_names, starting_value=0):
    results = []
    for d in function_dictionaries:
        result = d.copy()
        value = starting_value
        for function_name in function_names:
            value = d[function_name](value)
        result['result'] = value
        results.append(result)
    return results

pprint.pprint(apply_functions(function_dictionaries, ['f1', 'f2', 'f3', 'f4']))

# Output:
# [{'f1': <function add_one at 0x10ae58048>,
#   'f2': <function add_one at 0x10ae58048>,
#   'f3': <function add_one at 0x10ae58048>,
#   'f4': <function add_one at 0x10ae58048>,
#   'result': 4},
#  {'f1': <function add_one at 0x10ae58048>,
#   'f2': <function add_one at 0x10ae58048>,
#   'f3': <function add_one at 0x10ae58048>,
#   'f4': <function add_one at 0x10ae58048>,
#   'result': 4},
#  {'f1': <function subtract_one at 0x10aec4048>,
#   'f2': <function subtract_one at 0x10aec4048>,
#   'f3': <function subtract_one at 0x10aec4048>,
#   'f4': <function subtract_one at 0x10aec4048>,
#   'result': -4},
#  {'f1': <function subtract_one at 0x10aec4048>,
#   'f2': <function add_one at 0x10ae58048>,
#   'f3': <function add_one at 0x10ae58048>,
#   'f4': <function add_one at 0x10ae58048>,
#   'result': 2}]