计算一个项目在JavaScript的多维数组中出现多少次

时间:2018-08-29 18:45:40

标签: javascript arrays loops multidimensional-array counting

给出这样的多维数组:

 var arr = [
"apple",
["banana", "strawberry","dsffsd", "apple"],
"banana",
["sdfdsf","apple",["apple",["nonapple", "apple",["apple"]]]]
,"apple"];

面临的挑战是编写一个函数,该函数将数组和一个项目保留为参数,并返回该项目出现在数组中的次数。

我的第一个解决方案成功了:

function countItems(arr, item, sumarr = []) { // sumarr = array to store items matched

for (let i = 0; i < arr.length; i++ ){ // iterate on arr

    let isarray = arr[i].constructor === Array // if the element is a nested array

    if(isarray){  countItems(arr[i], item, sumarr) } // recursion

    let isin = arr[i] === item; // ELSE if the item is in the arr
    if(isin) { sumarr.push(arr[i])}; // add the element in the summ array



}
console.log(sumarr); // I preferred an array over a simple counter to be able to double check the result
return sumarr.length; // the length of the sum array show how many items founded
}

问题是,如果我尝试使用计数器(用于递增的变量)而不是用于存储值的数组,则会得到错误的结果(在这种情况下,console.log(countItems(arr, "apple"));而不是7,我得到了2) 。如果我做对了,那是因为递归函数带来了闭包,因为如果我使用全局变量,它将起作用。

在没有全局变量的情况下如何实现?

使用全局变量就是这样:

    let totc = 0;

function countItems(arr, item) { 


    for (let i = 0; i < arr.length; i++ ){ // iterate on arr
        let isarray = arr[i].constructor === Array; // if the element is a nested array
        if(isarray){  countItems(arr[i], item) } // recursion

        let isin = arr[i] === item; // ELSE if the item is in the arr
        if(isin) { totc ++;  };



    }
    return totc; // the length of the sum array show how many items founded
  }

5 个答案:

答案 0 :(得分:2)

您可以对数组采取递归方法,也可以检查该值并添加布尔值的结果。

function count(array, value) {
    return array.reduce((s, a) => s + (Array.isArray(a) ? count(a, value) : a === value), 0);
}

var array = ["apple", ["banana", "strawberry", "dsffsd", "apple"], "banana", ["sdfdsf", "apple", ["apple", ["nonapple", "apple", ["apple"]]]], "apple"];

console.log(count(array, 'apple'));

带有for循环的版本。

function count(array, value) {
    var i,
        sum = 0;

    for (i = 0; i < array.length; i++) {
        if (Array.isArray(array[i])) {
            sum += count(array[i], value);
            continue;
        }
        sum += array[i] === value;
    }
    return sum;
}

var array = ["apple", ["banana", "strawberry", "dsffsd", "apple"], "banana", ["sdfdsf", "apple", ["apple", ["nonapple", "apple", ["apple"]]]], "apple"];

console.log(count(array, 'apple'));

答案 1 :(得分:2)

我认为,如果您继续返回计数值并在计算中使用它,那么您将可以获得没有外部变量的最终数字:

function countItems(arr, item) {
  let totc = 0; // totc is now local
  for (let i = 0; i < arr.length; i++ ){ // iterate on arr
        let isarray = arr[i].constructor === Array; // if the element is a nested array
        if(isarray){  totc += countItems(arr[i], item) } // recursion, using the return value



        let isin = arr[i] === item; // ELSE if the item is in the arr
        if(isin) { totc ++;  };



    }
    return totc; // the length of the sum array show how many items founded
  }
}

请注意,我所做的唯一更改是在函数内部实例化了totc并获取了递归调用的结果并将其添加到本地总数中。

尼娜的答案更为优雅,但这也许会更容易理解。

答案 2 :(得分:1)

您可以使用arr.toString().split(",")迭代arr的平面版本,因此不需要递归。

var arr =  [
    "apple",
    ["banana", "strawberry","dsffsd", "apple"],
    "banana",
    ["sdfdsf","apple",["apple",["nonapple", "apple",["apple"]]]]
    ,"apple"];


var counts = {};


 arr.toString().split(",").forEach(e=>{
    counts[e] = (counts[e] || 0) +1
 })   

 console.log(counts.apple)

如果元素内部包含“,”,则不能使用,而是可以使用。flat()而不是.toString().split(",")

答案 3 :(得分:1)

我认为这是一种简单的方法,但是您可以纠结于此:

 function countItems(arr, item, count = 0){
     if(!arr.length) return count; //if the array is empty then there's nothing else to count
     let cTemp;
     if(Array.isArray(arr[0])){ //if the next item is an array
         cTemp = countItems(arr[0], item); //count the items in that array
     } else {
         cTemp = arr[0] === item ? 1 : 0; //if it's a string the compare it with item
         //1 if we found it
         //0 if we didn't
     }
     return countItems(arr.slice(1), item, count+cTemp);
     //count the items of the rest of the array and add what we found
     //arr.slice(1) is the rest of the array
     //cTemp is the count for the first item in the array
 }

当然可以重写为一行:

 let countItems = ([first, ...rest], item, count = 0) => !first ? count : countItems(rest, item, count + (Array.isArray(first) ? countItems(first, item) : +(first === item)))

答案 4 :(得分:0)

function numberOfItems(arr, item) {
    // Write the code that goes here
    let count = 0
    arr.forEach(element => {
        if(item === element) {
                count = count + 1;
        }
        if(Array.isArray(element)){
                count += numberOfItems(element,item);
        }
    });
    return count;
}