目标:给定一组混合类型可确定每个级别的元素数量。如果同一级别有两个子阵列,则每个子元素都会计入该级别的元素总数。
方法:
Array.prototype.elementsAtLevels = function( level, levelData ) {
if ( level == undefined ) { level = 0; } else { level += 1 }
if ( levelData == undefined ) { levelData = {}; }
if ( levelData[level] == undefined ) { levelData[level] = this.length} else { levelData[level] += this.length }
this.map(function(e, i) {if (Array.isArray(e)){ e.elementsAtLevels(level, levelData) }})
return levelData
}
测试用例:
[
1, // 0: 1
1, // 0: 2
1, // 0: 3
1, // 0: 4
[ // 0: 5
2, // 1: 1
2, // 1: 2
2 // 1: 3
],
[ // 0: 6
[ // 1: 4
3, // 2: 1
3 // 2: 2
],
[ // 1: 5
[ // 2: 3
4 // 3: 1
]
]
]
].elementsAtLevels()
// Object [ 6, 5, 3, 1 ]
问题: 有没有更有效的方法来计算它?
答案 0 :(得分:1)
我写了一些非常类似于你所拥有的东西,而且在一个非常基本的基准测试中,它的运行时间不到一半。
let a = [1,1,1,1,[2,2,2],[[3,3],[[4]]]];
Array.prototype.elementsAtLevels2 = function (level, lData) {
if (!level || !lData) {
level = 0;
lData = {};
}
if (!(level in lData)) {
lData[level] = this.length;
} else {
lData[level] += this.length;
}
this.forEach(function (v) {
if (Array.isArray(v))
v.elementsAtLevels2(level + 1, lData);
});
return lData;
}
console.log(a.elementsAtLevels2());
我猜测主要的性能提升可能来自forEach
vs map
,map
会创建一个新数组,其中forEach
没有。
此处位于JSBin
答案 1 :(得分:0)
这个递归函数应该做的工作
let arr = [1,1,1,1,[2,2,2],[[3,3],[[4]]]];
Array.prototype.elementsAtLevels = function(){
return this.reduce((acc, el, index, currentArray) => {
if(Array.isArray(el)){
return acc.concat(el.elementsAtLevels());
}
return [currentArray.length];
}, [])
}
console.log(arr.elementsAtLevels());
答案 2 :(得分:0)
这个东西和你的一样,但至少它给出了正确的结果:
function elementsAtLevel( array, result = [], level = 0 ){
result[level] = (result[level] || 0) + array.length
level++
for( const el of array ){
if( Array.isArray(el) )
elementsAtLevel(el, result, level)
}
return result
}
console.log( elementsAtLevel([1,1,1,1,[2,2,2],[[3,3],[[4]]]]) )
正确我的意思是一致:你把子阵列计算为第一级的元素,而不是其他任何元素。
这是一个原型版本:
Array.prototype.elementsAtLevel = function( result = [], level = 0 ){
result[level] = (result[level] || 0) + this.length
level++
for( const el of this ){
if( Array.isArray(el) )
el.elementsAtLevel(result, level)
}
return result
}
console.log( [1,1,1,1,[2,2,2],[[3,3],[[4]]]].elementsAtLevel() )
答案 3 :(得分:0)
这是我的看法。它类似于你的,但它不会改变原型,它使用数组而不是对象来返回。
function arrayCounter(arr, level, levelData) {
if (level === void 0) {
level = 0;
}
if (levelData === void 0) {
levelData = [];
}
//Set default value for level
if (levelData[level] === void 0) {
levelData[level] = 0;
}
//Count length
levelData[level] += arr.length;
//Loop through list items
for (var i = 0; i < arr.length; i++) {
var value = arr[i];
//If array, perform a subcount
if (Array.isArray(value)) {
levelData = arrayCounter(value, level + 1, levelData);
}
}
return levelData;
}
//TEST
var data = [1, 1, 1, 1, [2, 2, 2],
[
[3, 3],
[
[4]
]
]
];
console.log(arrayCounter(data));
&#13;