此处是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切换为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)
对于至少了解前三个错误以及我的功能出现问题的任何帮助/建议,将不胜感激。
答案 0 :(得分:1)
我假设您打算调用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
;
因此,每一行代表该过程的单个步骤。当然,确切的格式取决于您,但是我喜欢这种稍微扩展的方法,用于(稍微)更好的错误消息,以及在编辑之前,之后,中间等添加注释或更多内容的视图时,视图更轻松。< / p>
答案 1 :(得分:1)
map
本质上将每个元素替换为对该元素调用传递的函数的结果。由于您的函数返回的是两个int
的数组,因此结果将是一个数组数组,每个元素都包含两个int
。
有了这些知识,我们可以使用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)((int[]).init, list); }
更复杂的原因是:
1)reduce
的函数接受两个参数-到目前为止的归约结果和下一个元素。
2)reduce
假定传递的数组的第一个元素是精简的起点,除非传递了种子值。由于第一个元素是int
,而不是int[]
,因此我们需要传递种子值。 []
不会执行,因为它的类型为void[]
,所以我们需要创建一个空的int[]
。可以使用new int[0]
或如上所述的(int[]).init
来完成。
希望这会有所帮助-如果还有其他问题,请询问! :)