【问题标题】:Creating a Python lambda function from a string sequence从字符串序列创建 Python lambda 函数
【发布时间】:2018-06-23 17:11:41
【问题描述】:

我有一个包含 m 个元素和 n 个不同数字的列表,它们出现在字符串列表中。该列表遵循以下格式示例

eq = ['12', '2', '3', '-123', '-1', 'X']

注意,X 代表常数 1,而不是变量 1。我希望能够将其转换为 lambda 函数,该函数接受列表 x 并像此列表相加一样。对于我们的示例,函数将是

f(x) = x[1]*x[2] + x[2] + x[3] - x[1]*x[2]*x[3] - x[1] + 1

我知道如何使用普通函数执行此操作,但我想让它与 lambda 一起工作并碰壁。任何帮助,将不胜感激!

这是解决问题的函数:

def evaluateList(x, lst):
    num = 0
    for term in lst:
        if term[0] == "X":
            num += 1
        elif term[0] == "-":
            num -= reduce(lambda x,y: x*y, [x[int(y)-1] for y in term[1:]])
        else:
            num += reduce(lambda x,y: x*y, [x[int(y)-1] for y in term])
    return num

【问题讨论】:

  • 你能给出适合你的问题的函数定义吗?
  • @Carcigenicate 除非涉及到状态,这取决于实现可能有
  • @BowlingHawk95 我刚刚添加了工作功能实现。谢谢你的建议
  • @wjmccann 你遇到麻烦的原因是(如上所述),你不能在 lambda 中拥有状态。因为num 在迭代中改变值,所以该实现在 lambda 中不起作用。但一切都没有丢失!任何有状态的迭代算法都可以使用mapreducefilter 等组合子转换为无状态算法。该算法看起来与您上面的函数完全不同,但它是可行的。让我玩一下,看看我能想出什么。

标签: python string python-3.x function lambda


【解决方案1】:

我认为这很简单:

from operator import mul
from functools import reduce
prod = lambda L: reduce(mul, L, 1)
evaluateList = lambda(x, eq): sum(
    1 if expr == 'X' 
    else prod(-1 if i == '-' 
              else x[int(i)] 
              for i in expr) 
    for expr in eq)

【讨论】:

  • 真的希望 functools.reduce 使用 kwargs,这样您就可以使用 functools.partial 简化 prod 分配。
【解决方案2】:

显然我推荐def 实现:

from functools import reduce

eq = ['12', '2', '3', '-123', '-1', 'X']
x = [n for n in range(100)]

# Using an auxiliary function
def evaluate(n):
    if n == "X":
        return 1
    elif n[0] == "-":
        return reduce(lambda x, y: x * y, [x[int(y) - 1] for y in n[1:]])
    else:
        return reduce(lambda x, y: x * y, [x[int(y) - 1] for y in n])

print(sum(map(evaluate, eq)))

# As a pure lambda:

evaluate_lambda = lambda n: sum(map((lambda n: 1 if n == 'X' else (reduce(lambda x, y: x * y, [x[int(y) - 1] for y in n[1:]]) if n[0] == "-" else reduce(lambda x, y: x * y, [x[int(y) - 1] for y in n]))), eq))

print(evaluate_lambda(eq))

【讨论】:

    【解决方案3】:

    你可以使用functools.reduce两次,虽然结果不是很干净:

    from functools import reduce
    from operator import sub, add
    eq = ['12', '2', '3', '-123', '-1', 'X']
    _x = [6, 4, 1, 4, 5, 2, 4, 23, 2, 4]
    final_result = reduce(lambda x, y:[add, sub][y.startswith('-')](
      reduce(lambda c, d:c*d, [_x[int(i)] for i in x]) if x in eq else x, 
      reduce(lambda c, d:c*d, [_x[int(i)] for i in (y[1:] if y.startswith('-') else y)] if y != 'X' else [1])
      ), eq)
    

    print(final_result)
    x = _x
    print(x[1]*x[2] + x[2] + x[3] - x[1]*x[2]*x[3] - x[1] + 1)
    

    输出:

    -10
    -10
    

    但同样,预定义函数更易于阅读和扩展。

    另外,略短,sum:

    new_result = sum([1, -1][i.startswith('-')]*reduce(lambda x, y:x*y, [1] if i == 'X' else [x[int(c)] for c in (i[1:] if i.startswith('-') else i)]) for i in eq)
    

    【讨论】:

      【解决方案4】:

      这有点难看,但它有效

      from operator import mul
      a = lambda eq: sum([reduce(mul, [int(x) if x.isdigit() else [1,-1][x=='-'] for x in s]) for s in eq])
      
      
      print(a(['12', '2', '3', '-123', '-1', 'X']))  # outputs 1
      print(a(['126', '32', '3', '-2', 'X']))  # outputs 20
      

      edit:当然这只是一个游戏。始终使用最可读功能

      【讨论】:

      • [1,-1][x=='-'] 依赖于 True 为 1 而 False 为 0 的 Python 怪癖。当埋在大型模块 IMO 中时,这真的很难调试。如果可能的话,会避免这种情况。
      • 当然。但整个 lambda-ing 该功能是一个游戏。所以让我们玩得开心
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 2019-01-15
      • 2018-11-09
      • 1970-01-01
      • 2023-03-11
      • 2022-01-24
      相关资源
      最近更新 更多