使用高阶函数在数组中创建重复元素

Creating Duplicate Elements in an Array using Higher-Order Functions

这里是 D 语言的新手。我正在尝试使用高阶函数(即 fold!、reduce!、filter!、map!)来创建数组元素的副本。我声明我的泛型函数是纯函数,并试图将此任务作为一个单行函数来完成。到目前为止我最接近的是

auto dupList(T)(T[] list) pure { (return map!(a => a.repeat(2)); }

但这给了我以下输出

[[1,1],[2,2]]

而不是我真正想要的

[1, 1, 2, 2]

我是这样调用函数的

writeln(dupList(nums));

我一直在尝试使用 reduce 而不是使用 map,但是当我将 map 切换为 reduce 时,出现以下错误:

Error instantiated from here: `staticMap!(ReduceSeedType, __lambda2)` C:\D\dmd2\src\phobos\std\algorithm\iteration.d 3287
Error: template `D_Programs.duplist!int.duplist.__lambda2` cannot deduce function from argument types `!()(int, int)`, candidates are:  C:\D\dmd2\src\phobos\std\algorithm\iteration.d 3696
Error: template instance `D_Programs.duplist!int.duplist.F!(__lambda2)` error instantiating     C:\D\dmd2\src\phobos\std\meta.d 803
Error instantiated from here: `reduce!(int[])` D_Programs.d (refers to dupList)
Error `D_Programs.duplist!int.duplist.__lambda2` D_Programs.d (refers to dupList)
Error instantiated from here: `duplist!int` D_Programs.d (refers to where I'm calling from)

任何 help/advice 了解至少前三个错误以及我的功能哪里出错的任何人都将不胜感激。

我假设您打算调用 map!(a => a.repeat(2))(list)list.map!(a=>a.repeat(2))(两者相同),因为如果您不将实际列表传递给函数,它实际上就不会被调用叫了!

无论如何,map 和 reduce 都不会自己做你想做的事。 Map 转换单个元素,但既不能添加也不能删除元素。 Reduce(和 btw fold,它们基本相同)遍历整个数组,然后...好吧,将它减少到只有一个元素,就像将数组 1、2、3 变成单个元素 6 的求和函数一样。因为你想添加元素,你将需要外面的东西。

但首先,回避一下:您对 reduce 的调用无法编译,因为它传递了不正确的参数(或者其他什么,错误消息真的很糟糕,如果没有直接引用的代码打开就很难阅读也是,但它肯定指的是 lambda)。传递它你的 dupList 将不起作用,因为 dupList 需要一个数组,但 reduce 一次只处理两个元素,例如,sum(a, b).

无论如何,回到重点,你能得到的最接近的可能是 运行 map 之外的另一个函数来展平结果数组,或者换句话说,将它们连接在一起。有一个函数:http://dpldocs.info/experimental-docs/std.algorithm.iteration.joiner.2.html

建议一个可能的答案:

    return list .map!(a => a.repeat(2)) .joiner;

顺便说一句:一行函数被严重高估了。你通常最好把它写在多行上,即使是作为一个单一的语句,如果没有别的,你可以在错误消息上获得唯一的行号。我宁愿把它写出来可能是这样的:

    return
            list
                    .map!(a => a.repeat(2))
                    .joiner
            ;

所以每一行代表流程的一个步骤。当然,确切的格式取决于您,但我喜欢这种更加扩展的方法(稍微)更好的错误消息,并且在编辑以在之前,之后,中间添加评论或更多内容时更容易查看。

map 本质上是将每个元素替换为对该元素调用传递的函数的结果。由于您的函数 returns 是两个 int 的数组,因此结果将是一个数组数组,每个元素包含两个 ints.

有了这些知识,我们可以使用 std.algorith.iteration.joiner:

auto dupList(T)(T[] list) pure { return list.map!(a => a.repeat(2)).joiner; }

如你所见,使用reduce应该也是可以的,但有点复杂:

auto dupList(T)(T[] list) pure { return reduce!((a,b) => a~b~b)((T[]).init, list); }

它更复杂的原因是:

1) reduce 的函数有两个参数——到目前为止减少的结果和下一个元素。

2) reduce 假定传递的数组的第一个元素是缩减的起点,除非传递了种子值。由于第一个元素是 T,而不是 T[],我们需要传递一个种子值。 [] 不行,因为它的类型是 void[],所以我们需要创建一个空的 T[]。这可以通过 new T[0] 或如上所述 (T[]).init.

来完成

希望对您有所帮助 - 如果还有其他问题,请提问! :)