【问题标题】:Mapping arrays in Python using map, lambda, and functional programming workflows使用 map、lambda 和函数式编程工作流在 Python 中映射数组
【发布时间】:2018-01-13 06:19:39
【问题描述】:

我试图了解函数式编程语言是如何工作的,我决定在 python 中以函数式方式采用程序的方法,因为它是我感觉更舒服的语言。

我正在尝试,给定一个数组数组和一个有 2 个参数的函数,得到两个句子,每个数组中有两个元素。

如果不嵌套 lambda,我无法弄清楚如何做到这一点,但即使使用它们:

def sentence( x, y):
    return " this string contains %s and %s" % (x,y)
matrix = [['a','b'],['c','d']]

output = map(lambda a: map(lambda b: map(lambda c,d: sentence(c,d),b),a),matrix)

当然,因为我是一个老式的命令式程序员,所以我尝试使用老式的 for 循环来获得输出。当然有更好的方法,但是......

#print(output)
for i in output:
    #print(i)
    for j in i:
        #print(j)
        for k in j:
            print(k)

最后我只得到这个结果:

  File "fp.py", line 12, in <module>
    for k in j:
TypeError: <lambda>() missing 1 required positional argument: 'd'

所以是的,我想我在将值传递给函数时做错了,但我猜不出原因。

有什么想法吗?

【问题讨论】:

  • 你能展示你的输入和输出应该是什么样子吗?我无法准确查看您想要的内容。
  • 如果您的目标是教育,请考虑尝试coconut-lan.org。也看看toolz
  • 可能是我的错,因为我不是英语母语人士。输入是矩阵变量,包含两个数组 a,b 和 c,d。输出应该是一个包含两个字符串的数组,“这个字符串包含 a 和 b”和“这个字符串包含 c 和 d”。

标签: python functional-programming


【解决方案1】:

您有几个问题,这些结构嵌套的深度不足以保证嵌套循环。

对于要处理的每个级别的列表,您需要 1 个映射,因此如果要处理列表,则需要映射,如果要处理列表列表,则需要 2 个,依此类推。

在这种情况下,您很可能只想处理顶层(实际上这是因为您希望顶层中的每个列表都成为一个句子)。

def sentence( x, y):
return " this string contains %s and %s" % (x,y)
matrix = [['a','b'],['c','d']]

output = map(lambda a: sentence(a[0],a[1]), matrix)

# Print the top level
for i in output:
    print(i)

【讨论】:

  • 在 Python 2 中,您甚至可以将元组解包到位:lambda (a0, a1): sentence(a0, a1)。现在很明显,您只需要取消调用,并消除 lambda,调用 sentence(*a); itertools.stramap 这样做。
  • 哇,简单明了。谢谢!
【解决方案2】:

你做的太难了

def sentence( x, y):
    return " this string contains %s and %s" % (x,y)
matrix = [['a','b'],['c','d']]
# c will get sublists consequently
output = [sentence(*c)  for c in matrix]
print(output) # [' this string contains a and b', ' this string contains c and d']

你可以在上面的代码中避免使用

output = list(map(lambda c: sentence(*c), matrix))

【讨论】:

  • 经过深思熟虑,我强迫自己避免 for 和 while 循环,因为我想学习和实践纯函数式编程工作流程。
【解决方案3】:
  1. Python 风格指南推荐using list comprehensions instead of map/reduce
  2. String formatting using percent operator is obsolete,考虑使用 format() 方法
  3. 您需要的代码就是这个简单的单行代码

    output = [" 这个字符串包含 {} 和 {}".format(x, y) for (x, y) in matrix]

【讨论】:

    【解决方案4】:

    您的最后一个lambda 不会收到两个参数,因为它提供了b 的元素。它必须接收一个参数。

    这样的 lambda 阶梯在任何语言中都不好看。使用命名函数,它更具可读性。

    【讨论】:

      【解决方案5】:

      您根本不需要 lambda,但您确实需要解压缩参数,这在最新版本的 python 中已更改。以下代码适用于旧版本和新版本:

      def sentence(x_y):
          x, y = x_y
          return "Here is a sentence with {} and {}".format(x, y)
      
      matrix = [['a', 'b'], ['c', 'd']]
      output = list(map(sentence, matrix))
      

      【讨论】: