4
nums = [2 5 3 7]
result = []
result.push {x:nums[0]}
for n in nums.slice(1)
    result.push {n:n + result[-1].x}
log result
# [{x:2} {x:7} {x:10} {x:17}]

这很难用函数来表达,map因为每个元素都依赖于前一个元素。该算法的正确功能解决方案是什么?

4

6 回答 6

18

我知道的最简单的方法可以避免破坏性能的闭包、变量、额外的函数开销和全局变量:

result= [2, 5, 3, 7].map(function(a){ return { x: this[0]+=a }; }, [0]);

JS 提供了很少使用的第二个 .map() 参数来存储迭代之间您需要的任何状态。

它可能没有比这更简单的了,但不知道咖啡,对不起......

编辑:制作了一个双语言(js+cs)演示: http: //pagedemos.com/maptranforms/

于 2013-06-07T21:06:22.623 回答
8

您所描述的是扫描:也返回中间结果的折叠。scan1从 prelude.ls使用:

nums = [2 5 3 7]
scan1 (+), nums |> map ((num) -> { x : num })
# => [{x: 2}, {x: 7}, {x: 10}, {x: 17}]

如果您不需要数组中的对象而只需要添加中间结果,那么您可以完全放弃 map 操作,只需编写:

scan1 (+), [2 5 3 7] # => [2, 7, 10, 17]

scan1文档

于 2013-06-10T15:01:00.350 回答
3

您需要在某处保留一些状态信息。这是一个完成这项工作的 JavaScript 闭包:

var nums = [2, 5, 3, 7];
var result = nums.map(
    (function() {
        var lastX = 0;
        return function(n) {
            return {x : (lastX += n)};
        }
     }())
);
// result is [{x:2} {x:7} {x:10} {x:17}]
于 2013-06-07T20:40:25.320 回答
2

dandavis咖啡脚本中的答案是:

nums.map ((x)->{x: @[0] += x}), [0]

一个可能更清晰的变化

nums.map ((x)->{x: @accum += x}), {accum:0}

使用coffeescript理解(和累加器的相同想法)

accum = 0; z = ({x: accum += i} for i in nums)
于 2014-02-04T22:52:58.843 回答
2

JavaScript

保持总数的运行计数器,每次只添加新数字:

var nums = [2,5,3,7];

var createObject = function(nums){ 
    var result = [],
        total = 0;

    for(var i = 0; i < nums.length; i++){
        total += nums[i]; 
        result.push({"x": total});
    }

    return result;
};

JSFIDDLE

于 2013-06-07T20:52:37.960 回答
1
map (-> {x:it}) <| (fold ((acc, a) -> acc ++ [a + ((last acc) ? 0)]), []) <| [2, 5, 3, 7]
于 2013-10-25T19:16:18.473 回答