-3

I have JSON data as below: I want addition of the titleaccessed, numberoflogin for same id

    [ { id: '1651791',
        institutionname: null,
        fullname: 'Simi Abraham',
        username: ' ',
        totalrows: '46',
        numberoflogin: '1',
        logintimes: 1618963200,
        titleaccessed: '2' },
      { id: '1651791',
        institutionname: null,
        fullname: 'Simi Abraham',
        username: ' ',
        totalrows: '46',
        numberoflogin: '8',
        logintimes: 1619049600,
        titleaccessed: '18' }]
    
       The expected output is below
   
    [ { id: '1651791',
        institutionname: null,
        fullname: 'Simi Abraham',
        username: ' ',
        totalrows: '46',
        numberoflogin: '9',// addition of numberoflogin 
        logintimes: 1618963200,
        titleaccessed: '20' // addition of titleaccessed
        }]
Andy
  • 61,948
  • 13
  • 68
  • 95
Namrata
  • 1
  • 3
  • 1
    you'll need to process the data first to combine like id's – Bravo Jul 12 '21 at 12:21
  • Welcome to SO. You might find reading the site [help section](https://stackoverflow.com/help) useful when it comes to [asking a good question](https://stackoverflow.com/help/how-to-ask), and this [question checklist](https://meta.stackoverflow.com/questions/260648/stack-overflow-question-checklist). Code that you've worked on to solve the problem should include a [mcve], and be included in your question. – Andy Jul 12 '21 at 12:22
  • Does this answer your question? [Group objects by multiple properties in array then sum up their values](https://stackoverflow.com/questions/46794232/group-objects-by-multiple-properties-in-array-then-sum-up-their-values) – Keith Jul 12 '21 at 12:24

2 Answers2

1

Because the data needs to be grouped by ID, it would be possible to use find or filter to get entries with the same ID values. However, with longer lists that would get increasingly slow.

Alternatively one could use the ID as a key on an object, and then use Object.values(myObj) at the end to get the desired format:

const data = [{id: '1651791',institutionname: null,fullname: 'Simi Abraham',username: ' ',totalrows: '46',numberoflogin: '1',logintimes: 1618963200,titleaccessed: '2'},{id: '1651791',institutionname: null,fullname: 'Simi Abraham',username: ' ',totalrows: '46',numberoflogin: '8',logintimes: 1619049600,titleaccessed: '18'}];

const out = Object.values( // format the output as required
  data.reduce((acc, entry) => { // reduce to a single entry
    const accEntry = acc[entry.id];
    if (accEntry) { // if an entry exists (based on id)
      accEntry.numberoflogin = (parseInt(accEntry.numberoflogin) + parseInt(entry.numberoflogin)).toString(); // increment login count
      accEntry.titleaccessed = (parseInt(accEntry.titleaccessed) + parseInt(entry.titleaccessed)).toString(); // increment title access count
   } else acc[entry.id] = {...entry}; // else create entry
    return acc; // keep object for next iteration
  }, {}) // starting with an empty object
);
console.log(out, data);

With large amounts of entries this will run considerably faster than find or filter methods.

LaytonGB
  • 1,384
  • 1
  • 6
  • 20
  • 1
    This is close to how I would do it, but be careful as this mutates the original `data` - my code would've done `acc[entry.id] = {...entry};` to avoid that – Bravo Jul 12 '21 at 14:05
0

Well you can do this simply with the reduce() mehtod.

Something like this

let arrayVal =[ { id: '1651791',
        institutionname: null,
        fullname: 'Simi Abraham',
        username: ' ',
        totalrows: '46',
        numberoflogin: 1,
        logintimes: 1618963200,
        titleaccessed: 2 },
      { id: '1651791',
        institutionname: null,
        fullname: 'Simi Abraham',
        username: ' ',
        totalrows: '46',
        numberoflogin: 8,
        logintimes: 1619049600,
        titleaccessed: 18 },{ id: '1651792',
        institutionname: null,
        fullname: 'Simi Abraham',
        username: ' ',
        totalrows: '46',
        numberoflogin: 8,
        logintimes: 1619049600,
        titleaccessed: 18 }]
        
    let result = arrayVal.reduce((a, c) => {
    let filtered = a.filter(el => el.id === c.id);
    if(filtered.length > 0){
        a[a.indexOf(filtered[0])].titleaccessed += +c.titleaccessed ;
        a[a.indexOf(filtered[0])].numberoflogin += +c.numberoflogin;
    }else{
        a.push(c);
    }
    return a;
}, []);

console.log(result);

I would advise you to make sure the value of numberoflogin and titleaccessed must be integer or else you will have to convert it manually using parseInt() method and then add.

  • wouldn't you use `find` not `filter` to find the existing object? – Bravo Jul 12 '21 at 12:47
  • you're also adding ` to titleaccessed and numberoflogin, rather than the number in the object – Bravo Jul 12 '21 at 12:49
  • @Bravo It's clear with the she wants to add titleaccessed and numberoflogin and not the number to be increased. that why it's not number added and if its required that much thing one can do. – Sanjeev_gupta2812 Jul 12 '21 at 12:53
  • your solution doe not work, sorry you feel hard done by - it's clear what OP wants as a result as they have stated it in the question, and your code does not give `numberoflogin: '9'` and `titleaccessed: '20'` for id 1651791 – Bravo Jul 12 '21 at 12:53
  • @Bravo Okay got it. You can now try if it's working please remove this negative vote. – Sanjeev_gupta2812 Jul 12 '21 at 12:58
  • one more thing ... isn't `a[a.indexOf(filtered[0])]` just `filtered[0]` - and `let filtered = a.filter(el => el.id === c.id);` can be `let filtered = a.find(el => el.id === c.id);` and finally if you do that, `if(filtered.length > 0){` would be `if(filtered > 0){` - then rename filtered to found, and use `found.xxx` instead of `filtered[0].xxx` :p - just trying to help you be a better programmer – Bravo Jul 12 '21 at 13:03
  • @Bravo It's a pleasure being mentor by someone experienced. I would use find also in place of filter but I don't want for same ID's multiple entries. and also I tried with find first but didn't got what I wanted so I use filter in that case. As find only searches for the child elements so in case it would be a nested object it will skip search. You can post your answer with find too. I can check that where I was wrong . Thanks – Sanjeev_gupta2812 Jul 12 '21 at 13:15
  • try it with find, you wont' get duplicates – Bravo Jul 12 '21 at 13:51