Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.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 使用map/reduce反转列表_Python_Dictionary_Functional Programming_Reduce - Fatal编程技术网

Python 使用map/reduce反转列表

Python 使用map/reduce反转列表,python,dictionary,functional-programming,reduce,Python,Dictionary,Functional Programming,Reduce,我正在学习函数式编程的概念并尝试问题练习。 演习,, 使用map/reduce反转列表。 我的解决方案: lists = [ 1, 2, 3, 5 ,6] def tree_reverse(lists): return reduce(lambda a, x: a + [a.insert(0,x)], lists, []) print tree_reverse(lists) 输出: [6, 5, 3, 2, 1, None, None, None, None, None] 我不明白

我正在学习函数式编程的概念并尝试问题练习。 演习,, 使用map/reduce反转列表。 我的解决方案:

lists = [ 1, 2, 3, 5 ,6]

def tree_reverse(lists):
    return reduce(lambda a, x: a + [a.insert(0,x)], lists, [])

print tree_reverse(lists)
输出:

[6, 5, 3, 2, 1, None, None, None, None, None]
我不明白为什么列表中的元素数等于零

编辑:扩展嵌套列表案例的问题

 lists = [ 1 ,2 ,3 , [5,6,7], 8, [9, 0, 1 ,4 ]]

reduce操作将
None
追加到列表
a
的末尾,因为
a.insert(0,x)
将返回
None

因此,您在原地修改列表
a
,但同时附加
None

如果您将
reduce
操作重写为使用
for
循环,它将如下所示:

def reverse_list(lists):
    r = []
    for x in lists:
        val = r.insert(0,x)
        r = r + [val]  # val (the return value of r.insert) is None
    return r

reduce操作将
None
追加到列表
a
的末尾,因为
a.insert(0,x)
将返回
None

因此,您在原地修改列表
a
,但同时附加
None

如果您将
reduce
操作重写为使用
for
循环,它将如下所示:

def reverse_list(lists):
    r = []
    for x in lists:
        val = r.insert(0,x)
        r = r + [val]  # val (the return value of r.insert) is None
    return r

如果是嵌套列表。我张贴答案以供参考

lists = [ 1 ,2 ,3 , [5,6,7], 8, [9, 0, 1 ,4 ]]

def tree_reverse(lists):
    return  reduce(lambda a, x: ( map(tree_reverse, [x]) if isinstance(x,list) else [x] ) + a  , lists , [] )

print tree_reverse(lists) 
输出:

[[4, 1, 0, 9], 8, [7, 6, 5], 3, 2, 1]

如果是嵌套列表。我张贴答案以供参考

lists = [ 1 ,2 ,3 , [5,6,7], 8, [9, 0, 1 ,4 ]]

def tree_reverse(lists):
    return  reduce(lambda a, x: ( map(tree_reverse, [x]) if isinstance(x,list) else [x] ) + a  , lists , [] )

print tree_reverse(lists) 
输出:

[[4, 1, 0, 9], 8, [7, 6, 5], 3, 2, 1]

起初,我对Python的了解还不够好,但当您将问题标记为“函数式编程”并表示希望了解函数式编程的一般知识时,我想对您的问题给出一些一般性的解释。 首先,您应该重新思考
map
reduce
操作的作用以及它们的期望。让我们从
map
函数开始

列表的
map
函数(在函数式编程中,不是只有一个映射,每个泛型类型都有一个映射)对每个参数执行一个函数。该函数可以对单个参数进行操作并对其进行转换。此转换的结果将转换为一个新列表。一个重要的注意事项是,传递给
map
的函数只能看到一个元素,因此不能使用
map
本身来转换整个列表。您只能转换列表中的每个元素。但是改变顺序需要一个列表中至少有两个元素,并且一个映射只能得到一个元素。这就是为什么反向逻辑不能在
map
中,并且必须是
reduce
操作的一部分

另一方面,
reduce
函数需要一个函数,该函数接受两个相同类型的项,并返回一个相同类型的项。例如,reduce函数可以采用“+”函数。“+”是一个函数,它接受两个
int
,并返回一个新的
int
。签名基本上是
int+int=int
。reduce的本质是把两个东西合并成一个新的项目。例如,如果您有一个更复杂的类“Foo”,那么您必须提供函数来减少签名
Foo*Foo->Foo
。意思是将一个
Foo
作为第一个和第二个参数,并返回一个新的
Foo

注意
reduce
如何使用该功能也很重要。假设列表顶部有一个
[1,2,3,4,5]
,假设有一个
累加器函数
,该函数取两个
int
,将它们相加。你能想到的是,接下来会发生什么

  • reduce
    函数接受列表的前两个参数(本例中为1和2)
  • 将其传递给累加器功能(1+2=3)
  • 并用结果替换列表中的两个参数。[3,3,4,5]
  • 返回1)并重复该过程,直到列表中只有一项
  • 退回那一件
  • 因此,你可以想象发生了以下情况

    [1,2,3,4,5] -> 1 + 2 = 3
    [3,3,4,5]   -> 3 + 3 = 6
    [6,4,5]     -> 6 + 4 = 10
    [10,5]      -> 10 + 5 = 15
    [15]        -> Return just "15". Not a "[15]"
    
    实际上,内部流程通常会有一点不同。但这是一个你可以想象会发生什么的过程。请务必注意,您从不修改列表。您总是在该过程中创建新列表。另一个重要的注意事项。在
    reduce
    功能的末尾,您有一个单个项目的列表。但是
    reduce
    函数不会返回整个列表。它只返回单个元素。因此得到
    15
    一个
    int
    。您不会得到包含
    15
    的单个项目的列表。Reduce将只返回单个元素。不管是什么。另一种思考方式。您总是能准确地返回
    累加器函数的类型。如果传递一个接受两个
    int
    累加器函数
    ,则添加它们并返回一个新的
    int
    。reduce函数还将返回一个
    int
    。如果传递一个
    累加器函数
    ,该函数接受两个
    Foo
    类并返回一个新的
    Foo
    reduce
    函数还将返回一个
    Foo
    作为其结果。
    reduce
    的返回类型始终与
    累加器函数的类型相同

    现在,让我们把所有这些碎片放在一起。目标是扭转一个列表。第一件重要的事情是。您的结果类型将是一个
    列表
    。这也意味着传递到
    reduce
    的函数也必须返回
    列表。但由于输入和输出总是一样的。现在必须提供一个
    累加器函数
    ,该函数接受两个列表,并返回一个新列表

    但现在让我们退一步。如果您直接使用列表“[1,2,3,4,5]”作为输入来减少,会发生什么?简单的回答是,它不会起作用
    reduce
    将接受列表中的两个参数。但是你有一个int的列表。但是你的
    累加器函数
    需要两个列表而不是两个int。来解决这个问题
    [[1],[2],[3],[4],[5]] -> [2] ++ [1]       = [2,1]
    [[2,1],[3],[4],[5]]   -> [3] ++ [2,1]     = [3,2,1]
    [[3,2,1],[4],[5]]     -> [4] ++ [3,2,1]   = [4,3,2,1]
    [[4,3,2,1],[5]]       -> [5] ++ [4,3,2,1] = [5,4,3,2,1]
    [[5,4,3,2,1]]         -> Return first element [5,4,3,2,1]
    
    def tree_reverse(lists):
        return tree_reverse(lists[1:]) + [lists[0]] if lists else []
    
    reverse' :: [a] -> [a]  
    reverse' [] = []  
    reverse' (x:xs) = reverse' xs ++ [x]