我有一个深度数组(数组数组)。 我试图在不使用任何额外方法和JS设计(如闭包)的情况下创建一个正常函数。
这是一个有效的解决方案(但由于全局变量,这是一个糟糕的解决方案)
var counter = 0;
function findArray(array, item) {
for (var i = 0; i < array.length; i++) {
if (array[i] == item) {
counter++;
} else if (array[i].constructor === Array) {
findArray(array[i], item);
}
}
return counter;
}
这是一个 none 工作解决方案,试图避开全局计数器变量。
function findArray(array, item, counter) {
for (var i = 0; i < array.length; i++) {
if (array[i] == item) {
++counter;
}
if (array[i].constructor === Array) {
findArray(array[i], item, counter);
}
}
return counter;
}
我还想避免计数器输入参数,因为参数应该只是输入,输出变量不应该在函数参数内。另外,我想避免内置的方法,例如slice等。
注意:不应考虑算法的最佳性能。
有没有办法让计数器在函数内部工作?
函数调用如下所示:
findArray([1,[1,2,3],1,[5,9,1],6], 1,0);
输出应为数字 4 ,在此示例中(整数1是要在数组中搜索的数字)。
答案 0 :(得分:9)
这是递归的用例。 (以及在ES5中添加的Array.isArray
。)findArray
可以调用自身来查找数组中数组内的事件:
function findArray(array, item) {
var counter = 0;
for (var i = 0; i < array.length; i++) {
var entry = array[i];
if (entry == item){
counter++;
} else if (Array.isArray(entry)) {
// Add in the count of occurrences in the array, and any arrays in it
counter += findArray(entry, item);
}
}
return counter;
}
它也是Array#reduce
的用例:
function findArray(array, item) {
return array.reduce(function(counter, entry) {
if (entry == item) {
++counter;
}
if (Array.isArray(entry)) {
counter += findArray(entry, item);
}
return counter;
}, 0);
}
Array#reduce
在数组中的每个条目调用一次回调,在每次调用时传入累加器。累加器的初始值作为第二个参数提供(在某些情况下是可选的,但不是这里);回调返回累加器的更新版本,这是reduce
的最终返回值。
答案 1 :(得分:1)
你有正确的想法。您可以修改第一个递归函数,如下所示:
function findArray(array, item) {
var occurrences = 0;
for (var i = 0; i < array.length; i++) {
if (array[i] == item) {
// Found an occurrence.
occurrences++;
} else if (array[i].constructor === Array) {
// Add all occurrences in the sub-array i
occurrences += findArray(array[i], item);
}
}
return occurrences;
}
console.log(findArray([1, [1, 2, 3], 1, [5, 9, 1], 6], 1, 0));
或者使用reduce调用缩短它,它与上面的想法相同:
function findArray(array, item) {
return array.reduce((occur, e) =>
occur + ((Array.isArray(e)) ? findArray(e, item) : (e == item)), 0);
}
console.log(findArray([1, [1, 2, 3], 1, [5, 9, 1], 6], 1, 0));
答案 2 :(得分:0)
我相信这是最好的解决方案:
const countOccurs = (arr, val) =>
arr.reduce((prev, curr) => {
if (Array.isArray(curr)) {
return prev + countOccurs(curr, val);
}
if (curr !== val) {
return prev;
}
return prev + curr;
}, 0);
console.log(countOccurs([1,[1,2,3],1,[5,9,1],6], 1)); // 4
我们在这里做的是,我们将使用Array.prototype.reduce提供数组并检查值的任何出现。如果数组(curr)的实际值是一个数组,则该函数调用自身以检查它并将结果添加到计数器(prev)。
答案 3 :(得分:0)
使用JSBin:http://jsbin.com/sayimecezo/edit?html,js,console,output
您可以简单地展平嵌套数组,然后只对其进行过滤。 (为方便起见,在这里覆盖原型)。
Array.prototype.countDeep = function (n) {
return [].concat.apply([], this).filter(function (f) {
return f === n;
}).length;
}
console.log(([1,[1,2,3],1,[5,9,1],6]).countDeep(1));
//prints 4
播种到记忆值是微不足道的(虽然没必要);
Array.prototype.countDeep = function (n, seed) {
return (seed || 0) + [].concat.apply([], this).filter(function (f) {
return f === n;
}).length;
}
console.log(([1,[1,2,3],1,[5,9,1],6]).countDeep(1, 200));
//prints 204
答案 4 :(得分:0)
另一个也许更易理解的解决方案:
function sumValues(array) {
let counter = 0;
for (let item of array) {
if (Array.isArray(item)) {
counter += sumValues(item);
}
else {
counter += item;
}
}
return counter;
}