将函数映射到元组中的一个元素

4
我会用Haskell实现以下内容:

我有一个想法,类似于这样:

f :: Int -> (Int, Int)
-- for example:
f = `divMod` 12
foo :: [Int] -> (Int, Int)
foo = map (fmap (+1) . f)
-- foo [10, 11, 12, 13] = [(0,11),(0,12),(1,1),(1,2)]

是否有一种优雅的方式在 Python 中将此类映射到元组中(而无需查看f内部)?我能想到的最好方法是:

def foo(lst):
  for x in lst:
    a, b = f(x)
    yield a, b + 1

另一种可能性是:
def foo(lst):
  return map(lambda x: (f(x)[0], f(x)[1]+1), lst)

但我都不太满意这两种解决方案。第一种不是一个单独的表达式,不能很容易地内联。另一种解决方案具备这个特性,但它很丑陋,因为它在每次迭代中都不必要地调用了f()两次。有没有可能在迭代过程中以某种方式展开结果呢?

2个回答

3

首先将lst映射到f中:

try:
    # Python 2, forward compatible version of map
    from future_builtins import map
except ImportError:
    # Python 3, map is already an iterator
    pass

def foo(lst):
    return [(fxa, fxb + 1) for fxa, fxb in map(f, lst)]
    # or a generator expression for lazy evaluation
    # return ((fxa, fxb + 1) for fxa, fxb in map(f, lst)) 

1

好的,我找到了一个解决方案,它具有两个所需属性,但它不是很易读:

def foo(lst):
  return map(lambda a, b: (a, b+1), *zip(*map(f, lst)))

1
使用列表迭代,生成式为[(a, b+1) for a,b in *zip(*map(f, lst))] - ling7334
为什么需要使用 map()?为什么不直接使用生成器表达式呢? - Martijn Pieters
@ling7334:在那种情况下,*zip(*map(..)) 更加浪费时间。 - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接