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

问题描述 投票:1回答:4

给定一个像这样的多维数组:

 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
}

问题是,如果我尝试使用一个计数器(一个变量来递增)而不是一个数组来存储值,我得到一个错误的结果(在这种情况下,而不是7,console.log(countItems(arr, "apple"));我有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
  }
javascript arrays loops multidimensional-array counting
4个回答
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
投票

您可以对数组采用递归方法或检查值并添加布尔值的结果。

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
投票

我认为这是一个简单的方法,但你可以纠结于它:

 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)))

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(",")一起使用

© www.soinside.com 2019 - 2024. All rights reserved.