10

我试图命名我认为是高阶函数的新想法。对于重要的部分,这里是用 Python 和 Haskell 来演示这个概念的代码,后面会解释。

Python:

>>> def pleat(f, l):
       return map(lambda t: f(*t), zip(l, l[1:]))
>>> pleat(operator.add, [0, 1, 2, 3])
[1, 3, 5]

哈斯克尔:

Prelude> let pleatWith f xs = zipWith f xs (drop 1 xs)
Prelude> pleatWith (+) [0,1,2,3]
[1,3,5]

正如您可能推断的那样,正在迭代序列,利用相邻元素作为您传递它的函数的参数,将结果投影到新序列中。那么,有人看过我们创建的功能吗?这对职能社区的人来说是不是很熟悉?如果不是,我们给它取什么名字?

---- Update ----

褶皱赢了!

Prelude> let pleat xs = zip xs (drop 1 xs)
Prelude> pleat [1..4]
[(1,2),(2,3),(3,4)]

Prelude> let pleatWith f xs = zipWith f xs (drop 1 xs)
Prelude> pleatWith (+) [1..4]
[3,5,7]
4

16 回答 16

17

嗯……对位。

(`ap` tail) . zipWith

不配取名。

顺便说一句,水银 说:

 zip`ap`tail

连续数字的阿兹特克神

于 2010-09-23T03:29:47.777 回答
6

由于它类似于“折叠”,但不会将列表折叠成单个值,那么“折痕”呢?如果你继续“折痕”,你最终会“折叠”(有点)。

我们可以用一个烹饪比喻,称之为“捏”,就像捏馅饼皮一样,尽管这可能暗示了一个圆形拉链,列表的最后一个元素与第一个元素配对。

def pinch(f, l):
    return map(lambda t: f(*t), zip(l, l[1:]+l[:1]))

(如果你只喜欢“crease”或“pinch”中的一个,请在评论中注明。这些应该是单独的建议吗?)

于 2010-09-22T23:25:36.703 回答
6

在 Python 中,meld等效项在 itertools 收据中,并被称为成对。

from itertools import starmap, izp, tee

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

所以我称之为:

def pairwith(func, seq):
    return starmap(func, pairwise(seq))

我认为这是有道理的,因为当您使用标识函数调用它时,它只会返回对。

于 2010-09-23T01:25:04.967 回答
5

这是 Python 的另一种实现,如果l它也是生成器,它也可以工作

import itertools as it

def apply_pairwise(f, l):
    left, right = it.tee(l)
    next(right)
    return it.starmap(f, it.izip(left, right))

我认为apply_pairwise是一个更好的名字

于 2010-09-22T23:18:03.127 回答
4

我真的在 Python 的任何地方都看不到任何编码的名称,这是肯定的。“合并”很好,但可以在各种其他情况下使用。“犁”往往未被使用,并提供了一个很好的视觉效果,可以稳定地穿过土壤。也许我只是花太多时间在园艺上。

我还扩展了该原理以允许函数接收任意数量的参数。

您也可以考虑:褶皱。它很好地描述了您列出列表(如一长串织物)并将其部分捆绑在一起的方式。

import operator

def stagger(l, w):
    if len(l)>=w:
        return [tuple(l[0:w])]+stagger(l[1:], w)
    return []

def pleat(f, l, w=2):
    return map(lambda p: f(*p), stagger(l, w))

print pleat(operator.add, range(10))
print pleat(lambda x, y, z: x*y/z, range(3, 13), 3)
print pleat(lambda x: "~%s~"%(x), range(10), 1)
print pleat(lambda a, b, x, y: a+b==x+y, [3, 2, 4, 1, 5, 0, 9, 9, 0], 4)
于 2010-09-23T00:20:23.280 回答
2

zipWithTailadjacentPairs

于 2010-09-23T00:49:46.237 回答
2

我投票赞成smearWithsmudgeWith因为这就像您在整个列表中涂抹/涂抹操作。

于 2010-09-23T01:17:56.667 回答
2

这看起来像红宝石的each_cons

ruby-1.9.2-p0 > (1..10).each_cons(2).to_a

=> [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10]] 
于 2010-09-23T06:18:28.917 回答
2

这让我想起了图像处理中的卷积。但不确定这在数学上是否正确。

于 2010-09-23T10:57:01.063 回答
2

我认为这是普通 zip 版本的通用变体window。现在不在 ghci 终端,但我认为window n = take n . tails. 那么你的功能是zipWith (\[x,yj -> f x y) . window 2. 当 f 是 type 时,这种风格自然会更好[a] -> b

于 2010-09-23T11:55:21.770 回答
2

在 C++ 标准模板库中,它被称为相邻差异(尽管运算符可以是任何运算,而不仅仅是减法)

于 2010-09-24T07:20:22.620 回答
1

因此,因为似乎没有名称,所以我建议使用“合并”或简单的“合并”,因为您正在将相邻的值合并在一起。

所以合并已经被采用,所以我现在建议“融合”(或“合并”,但可能太接近“合并”)

例如:

meld :: (a -> a -> b) -> [a] -> [b]
meld _ [] = []
meld f xs = zipWith f (init xs) (tail xs)

可以用作:

> meld (+) [1..10]
[3,5,7,9,11,13,15,17,19]
> meld compare "hello world"
[GT,LT,EQ,LT,GT,LT,GT,LT,GT,GT]

第二个例子没有真正的意义,但却是一个很酷的例子。

于 2010-09-22T23:35:12.327 回答
1

使用 Mathematica

加上 @@@ Partition [{0, 1, 2, 3}, 2, 1] 或这些更详细的替代方案中的任何一个

Apply[Plus, Partition[{0, 1, 2, 3}, 2, 1], {1}]
Map[Apply[Plus, #] &, Partition[{0, 1, 2, 3}, 2, 1]]

我已经在许多语言中使用并享受过这个高阶函数,但我在 Mathematica 中最喜欢它;它似乎简洁灵活地分解为 Partition 和 Apply with levelspec 选项。

于 2010-09-23T05:37:14.427 回答
1

我很想将其称为轮廓,因为我已将其用于音乐软件中的“轮廓”处理-当时我将其称为 twomap 或类似的愚蠢东西。

音乐处理中还有两个特定的命名“轮廓”,一个是粗轮廓 - 音高是向上还是向下。另一个是精致的轮廓,轮廓要么向上,向下,向上跳跃或向下跳跃,但我似乎无法找到半音差异必须有多大才能实现跳跃的参考。

于 2010-09-23T17:18:09.103 回答
1

好成语!我只需要在 Perl 中使用它来确定连续事件之间的时间。这就是我最终的结果。

sub pinch(&@) {
  my ( $f, @list ) = @_;
  no strict "refs";

  use vars qw( $a $b );

  my $caller = caller;
  local( *{$caller . "::a"} ) = \my $a;
  local( *{$caller . "::b"} ) = \my $b;

  my @res;
  for ( my $i = 0; $i < @list - 1; ++$i ) {
    $a = $list[$i];
    $b = $list[$i + 1];
    push( @res, $f->() );
  }
  wantarray ? @res : \@res;
}

print join( ",", pinch { $b - $a } qw( 1 2 3 4 5 6 7 ) ), $/;
# ==> 1,1,1,1,1,1

如果我让它依赖于List::Util ,实现可能会更漂亮,但是......嗯!

于 2010-09-29T15:57:54.327 回答
0

BinaryOperate 或 BinaryMerge

于 2010-09-23T01:22:01.247 回答