减少a'原始'javascript数组转换为更紧凑的(对象)数组
Reducing a 'raw' javascript array into a more compact array (of objects)
在javascript中,我正在寻找一种整洁的方法来处理数组,使集合中的短重复序列(元组)变成更紧凑的集合。我想将长度3n的数组转换为长度n 这里有一个假想的例子: 或者,如果 我正在寻找一个非常像 高性能的好处是,但最终解决方案应该可读、可维护和可用。// A flat (1-dimensional) array of numbers for input
var input = [
1, 11, 5,
2, 12, 10,
3, 13, 6,
4, 14, 11,
... ];
// A custom "lambda". This is my main intent, the rest is just plumbing.
var formatData = function(a,b,c) {
return { foo: a, bar: b, woot: c };
};
var output = input.reduceMulti(3, formatData); // ficticious 'reduceMulti'!
// output:
// [
// { foo: 1, bar: 11, woot: 5 },
// { foo: 2, bar: 12, woot: 10 },
// { foo: 3, bar: 13, woot: 6 },
// { foo: 4, bar: 14, woot: 11 },
// ...
// ]
formatData
返回了不同的内容,那么output
中的那些对象可以很容易地成为字符串或数组。reduce
的解决方案,除了能够减少到一个以上的值。
您仍然可以使用reduce
,它还将索引和数组作为参数:
var formatData = function(x, y, z) {
return [x, y, z]
}
var reduceMulti = function(n, f, xs) {
return xs.reduce(function(acc, x, i, xs) {
if (i % n === 0) {
acc.push(f.apply(null, xs.slice(i, i+n)))
}
return acc
},[])
}
reduceMulti(3, formatData, input)
//^ [[1,11,5], [2,12,10], [3,13,6], [4,14,11]]
如果给n
一个值3
,那么就必须传递一个需要3个参数的函数。
我将从一个简单的小例程开始,将数组划分为大小相等的段:
function partition(arr, n) {
return arr.length ? [arr.splice(0, n)].concat(partition(arr, n)) : [];
}
还有一个小和函数:
function sum(arr) { return arr.reduce(function(s, v) { return s + v; }); }
现在,我们将对原始数组进行分区,并将其映射到统计度量的对象:
partition(input, 3).map(function(seg) {
return {
max: Math.max.apply(0, seg),
min: Math.min.apply(0, seg),
mean: sum(seg)/seg.length};
};
})
如果您更喜欢非递归分割器:
function partition(arr, n) {
var result = [];
while (arr.length) { result.push(arr.splice(0, n)); }
return result;
}
这利用了Array#splice
的行为,即它修改数组以删除指定的元素,并返回已删除元素的数组。
如果你真的想实现你提出的语法,那么你需要在Array原型上放reduceMulti
,而不是我建议的:
Array.prototype.reduceMulti = function(n, reducer) {
return partition(this, n).map(reducer);
}
var output = input.reduceMulti(3, formatData);
将问题分解为几个步骤:对平面数组进行分组,使用map()
对每个数组进行变换,并使用reduce
计算和。
var r= [
1, 11, 5,
2, 12, 10,
3, 13, 6,
4, 14, 11,
];
function flatToGrouped(r, width){
var o=[];
for(var i=0, mx=r.length; i<mx; i+=width){
o.push(r.slice(i, i+width) );
}
return o.filter(Boolean);
}
function report(a,_,__){
return {
min: Math.min.apply(0,a),
max: Math.max.apply(0,a),
mean: a.reduce( function(a,b,_,__){ return a+b; } )
}
}
flatToGrouped(r, 3).map(report);
额外的形式参数看起来很奇怪,但它们使函数运行得比其他方面更快(我刚刚发现arity匹配可以改进优化——我告诉大家)。
编辑:我没有意识到最初的数组是平的。您仍然可以在itemtransformer上使用简单的映射,并使用收集器生成要分析的n级数组。通过将它们分成两部分,您不会被锁定在reduce中,而是锁定在数组可以做的任何事情(map/reduced/filter/etc)中。
- 将数组对象传递到struts2中的操作类
- 如何使用jquery返回php-json数组对象
- 从其名称获取javascript数组对象
- 值未与数组对象绑定
- 如何按数组/对象值的倍数过滤对象数组
- 在表中显示数组对象
- 在数组对象中分组
- 将第二个或多个数组推送到数组对象 AngularJS 中
- 重新排列 JavaScript 数组/对象
- 键上的javascript数组对象过滤器
- handontable:在不更改数据数组/对象的情况下隐藏某些列
- 用于跟踪购物车可用性的Javascript数组/对象/哈希表
- 重建有角度的java脚本数组对象
- 对JSON数组对象进行排序
- 连接与数组对象相关的文本:方式和位置
- 哪些浏览器和版本支持将常见的类数组对象直接传递到fn.apply()
- 如何使用Handlebars循环数组对象和模板
- 是否可以引用JS数组/对象中的另一个元素
- Javascript中的名称索引-数组/对象
- 数组长度不等于数组对象