2

I have an array of objects with known keys. And I want to count how many objects have a particular key with a certain value. Currently I made it up with this:

counter = () => {
        if (Array) {
            let a = 0;
            for (let i = 0; i < Array.length; i++) {
                if (Array[i].key === '1' || Array[i].key === '2' || Array[i].key === '3' || Array[i].key === '4' || Array[i].key === '5' || Array[i].key === '6' || Array[i].key === '7') {
                    a++;
                }
            }
            return a;
        }
    }

I tried reduce() and find() while converting arrays to objects and vice versa but with no luck yet.
I suppose there should be more elegant way to perform such a simple task in plain vanilla JS ES6 or ES7. Ideally a oneliner. No lodashing please.

All other questions here target searching in elements, when mine touch one level deeper.

8
  • 3
    post your array of object Commented Sep 6, 2018 at 16:17
  • what is if(Array) supposed to do? Commented Sep 6, 2018 at 16:18
  • myArray.filter(item => item.someProp === value).length? Commented Sep 6, 2018 at 16:18
  • 3
    Possible duplicate of How to count the number of certain element in an array? Commented Sep 6, 2018 at 16:20
  • @smart-googler it indeed doesn't matter in this situation Commented Sep 6, 2018 at 16:41

5 Answers 5

2

You can try to use the javascript filter function: Something like:

var count = array.filter(function(e){
                  return (e.key === '1' || e.key === '2' || e.key === '3' || e.key === '4' || e.key === '5' || e.key === '6' || e.key === '7')

}).length;

Basically, this filter your array of objects by the keys you want, at the end it calculates the array length.

Sign up to request clarification or add additional context in comments.

Comments

1

Sure, here is that oneliner:

 array.reduce((count, el) => count + +["1", "2", "3", "4", "5", "6", "7"].includes(el.key), 0)

This uses includes to check wether el.key is one of the numbers, then the resulting boolean is turned into a number with the unary plus (true -> 1, false -> 0), and that is added to count for each element, resulting in the total count.

2 Comments

reduce() looks powerful, could you explain what's going on here?
@igniter added a short explanation.
1

Try using

var count = b.filter(element => {return element.key == requiredKey;}).length;

count will have the number of objects with same key

Comments

1

You can do this with .filter() fairly easily, like so:

The idea is that you want to filter down to only the objects that match, and then use a .length to get the count at the end. We can know if an element matches by checking if the object's key property value is included in the list of keys you are searching for.

var test = [
{ key: '1' },
{ key: '3' },
{ key: '2' },
{ key: '7' },
{ key: '5' },
{ key: '8' },
]
var keysToSearch = ['1', '2', '3', '4', '5', '6', '7'];

function counter (objs, searchKeys) {
  return objs.filter(obj => searchKeys.includes(obj.key)).length;
}

console.log(counter(test, keysToSearch));

EDIT

Here's a solution that does the same thing as the above, but doesn't create a new array with .filter().

var test = [
{ key: '1' },
{ key: '3' },
{ key: '2' },
{ key: '7' },
{ key: '5' },
{ key: '8' },
]
var keysToSearch = ['1', '2', '3', '4', '5', '6', '7'];

function counter (objs, searchKeys) {
  var count = 0;
  for (var obj of objs) {
    if (searchKeys.includes(obj.key)) { count++; }
  }
  return count;
}

console.log(counter(test, keysToSearch));

5 Comments

Why create a new array to do this?
@charlietfl which array are you referring to?
filter() returns new array. Also OP is starting with array of objects , not a single object and also wants to match values
@charlietfl Oh I missed the array of objects part. I will fix. Also updated with an answer that creates no new arrays
@charlietfl Updated. I think I got it all now. Thank you for your comment, I didn't fully understand the question at first
0

Do not create new array, one line, loop on keys to reduce the loop iterations.

Reduce work like :

array.reduce((accumulator, oneArrayValue) => {
  // Function where treatment are done
  return theAccumulatorValueForNextLoopIteration;
}, initialValueOfTheAccumulator);

function counter(obj, keys) {
  // void 0 equals undefined
  // So it's equivalent to typeof x !== 'undefined'

  // tmp is the accumulator, it's value is setted up at 0
  // then it becomes what you return after every loop
  return keys.reduce((tmp, x) => obj[x] !== void 0 ? tmp + 1 : tmp, 0);
}

console.log(counter({
  1: 'hey',
  2: 'how',
  8: 'you',
  12: 'doing',
  15: 'baguette',
}, [
  '1',
  '2',
  '3',
  '4',
  '5',
  '6',
  '7',
]));

1 Comment

Could you please explain what 1) 'void 0' and 2) 'tmp, 0' mean here in plain English?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.