简体   繁体   中英

Count the number of occurrences and add it to grouped objects in a JSON array

Here's my input value -

var input = [
    {
      status: 'yes',
      data: ['a', 'b', 'c', 'd'],
      score: 2,
      rank: 2,
    },
    {
      status: 'yes',
      data: ['a', 'b', 'c'],
      score: 9,
      rank: 2,
    },
    {
      status: 'yes',
      data: ['a', 'b', 'c'],
      score: 8,
      rank: 2,
    },
    {
      status: 'no',
      data: ['a', 'b', 'c', 'd'],
      score: 12,
      rank: 3,
    },
    {
      status: 'no',
      data: ['a', 'b', 'c'],
      score: 9,
      rank: 3,
    },
    {
      status: 'no',
      data: ['a', 'b', 'c', 'd'],
      score: 5,
      rank: 3,
    },
  ]

And here's what I'm trying to get as an output value -

  [
    {
      status: 'yes',
      data: ['a', 'b', 'c', 'd'],
      occurrence: 1,
      rank: 2,
    },
    {
      status: 'yes',
      data: ['a', 'b', 'c'],
      occurrence: 2,
      rank: 2,
    },
    {
      status: 'no',
      data: ['a', 'b', 'c', 'd'],
      occurrence: 2,
      rank: 3,
    },
    {
      status: 'no',
      data: ['a', 'b', 'c'],
      occurrence: 1,
      rank: 3,
    },
  ]

The idea is to -

  1. Remove the score parameter from all the objects
  2. Add the occurrence parameter to all the objects
  3. Assign the "occurrence" value ie the number of times we see the same data being repeated as per each of the status

Here's the code that I'm using (adopted from the 2nd half of this solution ) -

const res = Array.from(input.reduce((acc, {score, ...r}, index) => {
  const key = JSON.stringify(r);
  const current = acc.get(key) || {...r, occurrence: 0};  
  return acc.set(key, {...current, occurrence: current.occurrence + index});
}, new Map).values());
console.log(res);

But that's producing an unexpected output that looks like this -

[
  {
    "status": "yes",
    "data": ["a","b","c","d"],
    "rank": 2,
    "occurrence": 0
  },
  {
    "status": "yes",
    "data": ["a","b","c"],
    "rank": 2,
    "occurrence": 3
  },
  {
    "status": "no",
    "data": ["a","b","c","d"],
    "rank": 3,
    "occurrence": 8
  },
  {
    "status": "no",
    "data": ["a","b","c"],
    "rank": 3,
    "occurrence": 4
  }
]

There's something that I'm missing to get the correct occurrences & I can't for the life of me understand what.

I will do that this way

 const input = [ { status: 'yes', data: [ 'a', 'b', 'c', 'd' ], score: 2, rank: 2 } , { status: 'yes', data: [ 'a', 'b', 'c' ], score: 9, rank: 2 } , { status: 'yes', data: [ 'a', 'b', 'c' ], score: 8, rank: 2 } , { status: 'no', data: [ 'a', 'b', 'c', 'd' ], score: 12, rank: 3 } , { status: 'no', data: [ 'a', 'b', 'c' ], score: 9, rank: 3 } , { status: 'no', data: [ 'a', 'b', 'c', 'd' ], score: 5, rank: 3 } ] , result = input.reduce((a,{status,data,rank}) => { let same = a.find( x => x.status === status && x.rank === rank && JSON.stringify(x.data) === JSON.stringify(data) ) if (!same) a.push({ status, data: [...data], occurrence: 1, rank }) else same.occurrence++ return a },[]) console.log( result )
 .as-console-wrapper {max-height: 100%!important;top:0}

I really didn't catch what did you want to do with occurence value. In your example you were showing:

status: 'no', data: ['a', 'b', 'c', 'd'], occurrence: 2,

And why is here occurence equals 2 whereas 'no' is the first status with this value?

At first try to remove current.occurrence + index and leave just current.occurrence if it will be always zero it will be correct to make next steps to calculate what you want.

I doubt that you need index there. Try to explain, and it helps to provide a decision.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM