最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Use reduce to shorten array - Stack Overflow

programmeradmin1浏览0评论

Use reduce to find number of times an items is in an array. The array could have arrays inside recursively.

var foo = [
  1,
  [2, 3, 4], 
  4, [5,6,7], 4
];

bar(foo, 4) would return 3.

Use reduce to find number of times an items is in an array. The array could have arrays inside recursively.

var foo = [
  1,
  [2, 3, 4], 
  4, [5,6,7], 4
];

bar(foo, 4) would return 3.

Share Improve this question edited Jan 3, 2016 at 1:23 Aᴍɪʀ 7,8033 gold badges39 silver badges54 bronze badges asked Dec 30, 2015 at 19:09 NorCalKnockOutNorCalKnockOut 8783 gold badges11 silver badges27 bronze badges 3
  • 2 In your example, why would bar(foo, "a") return 3, although "a" occurs only twice in its input? – Codor Commented Dec 30, 2015 at 19:16
  • @NorCallKnockOut Thanks for the clarification. – Codor Commented Dec 30, 2015 at 19:21
  • foo is not an object, it's an array – edc65 Commented Dec 30, 2015 at 19:22
Add a ment  | 

5 Answers 5

Reset to default 4

Try this one using Array.prototype.reduce.

var foo = [1, [2, 3, 4], 4, [5, 6, 7], 4];

function f(arr, item) {
  return arr.reduce(function (s, i) {
    if (Array.isArray(i)) return s+f(i, item);
    return s+(i==item?1:0);
  }, 0);
}

console.log(f(foo, 4))

The function f is a recursive function. We loop over all the items and reduce them to one number. The function would be called on all the inner arrays as well, and for the non-array items, we just check them to be equal to the desired item.

You can count all items with one call with Array.prototype.forEach()

The forEach() method executes a provided function once per array element.

And a check if the element is an array, then the function is called again with the array as parameter.

var foo = ["a", ["b", "c", "d"], "a"],
    object = {};

function count(a, o) {
    a.forEach(function (b) {
        if (Array.isArray(b)) {
            count(b, o);
        } else {
            o[b] = (o[b] || 0) + 1;
        }
    })
}

count(foo, object);
document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');

So if you want a recursion (And it'll work in any browser):

var foo = [
    "a",
    ["b", "c", "d"], 
    "a"
];

function bar(arr, item) {
    var count = 0;
    if (arr.length == 0) {
        return 0;
    }

    for (var i = 0, l = arr.length; i < l; i++) {
        var v = arr[i];
        if (typeof v === "string") {
            if (v === item) {
                count++;
            }
        } else {
            count = count + bar(v, item);
        }
    }

    return count;
}

console.log(bar(foo, "a"));

Here is another functional type of interpretation that doesn't require an external state, although would be more inefficient.

var foo = [
  "a",
  ["b", "c", "d"],
  ["a", "b"],
  "a"
];

function flatten( arr ){
  return arr.reduce(function( ret, curr ){
    return ret.concat( Array.isArray( curr ) ? flatten( curr ) : [ curr ] );
  }, []);
}

function filterBy( arr, val ){
  return arr.filter(function( item ){
    return item === val;
  })
}

console.log( flatten( foo ) );
console.log( filterBy( flatten( foo ), 'a') );
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>

Using underscore you can count number of occurrence of each element with this code:

_.countBy(_.flatten(array), _.identity)

So function foo can be implemented like this:

function bar(foo, element){
    return _.countBy(_.flatten(foo), _.identity)[element];
}
var foo = ["a", ["b", "c", "d"], "a"]
console.log(bar(foo, "a"));

Although this solution isn't recursive I find it worth mentioning.

发布评论

评论列表(0)

  1. 暂无评论