3

I'm trying to fix this, but I'm a little bit stuck and need some help/advise. I'm trying to get to know es6 better and better, but I'm clueless on what's the best way to fix my problem.

I have a large json I'm fetching which looks somewhat like this:

[
    {
        "company": "Google",
        "location": "USA",
        "email": null
    },
    {
        "company": "Microsoft",
        "location": "USA",
        "email": "[email protected]"
    },
    {
        "company": "Google",
        "location": "NLD",
        "email": "[email protected]"
    }
]

I display these in a table and want to add checkbox filters but I also want to add a count next to it, like so:

[x] Google (2)
[ ] Microsoft (1)
// other function call
[ ] [email protected] (2)

I have this function I call every every key (company, location, email):

function filterArr(data, key) {

    data.forEach(element => {

        let countedData = data.filter((el) => {
            return el[key] == element[key]
        }).length;
// console.log(element[key] + ": " + countedData);
    });

    data = data.filter((item, index, self) => self.findIndex( t => t[key] === item[key] && item[key] != null) === index )
// console.log(data)
    return data;
}

filterArr(data, "company");

The output I'm trying to achieve with the above function is: Google: 2 Microsft: 1

The foreach is correctly counting the key values, but obviously logging the following: Google: 2 Microsoft: 1 Google: 2

And the filter console.log shows Google and Microsoft (just once, like I want :)

Now I need to combine these 2, but I'm not sure how to and what's the best way to do so. (see my fiddle: https://jsfiddle.net/z359qo1d/)

Do you know what to do next?

2 Answers 2

7

Array.prototype.reduce is a perfect match for what you want

function filterArr(data, key){
  return data.reduce( (result, current) => {
    if(!result[current[key]]){
      result[current[key]] = 1;
    } else {
      result[current[key]] += 1;
    }
    return result;    
  }, {})
}

The above will return an object like this

{
  Google: 2,
  Microsoft: 1
}
Sign up to request clarification or add additional context in comments.

3 Comments

My favorite answer. Replace if(!result[current[key]]) by if(! (current[key] in result) ) or I guess the counter never gets incremented...
@RaphaMex good catch. Updated so i initialize to 1 instead of 0
Thanks! Works like a charm, thought I almost got the solution myself, but this works great!!
1

I'd do it a little bit differently:

let _in = [
{
    "company": "Google",
    "location": "USA",
    "email": null
},
{
    "company": "Microsoft",
    "location": "USA",
    "email": "[email protected]"
},
{
    "company": "Google",
    "location": "NLD",
    "email": "[email protected]"
}
]

function countEm(accum, each) {
  if (! accum[each.company] )
    accum[each.company] = 0
  accum[each.company] += 1
  return accum
}

console.log(_in.reduce(countEm, {}))

Comments

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.