2

Suppose I have an object as,

const emailCount = {'vik@g.com':4,'sri@y.com':9}

And I have an array of object as,

const emailDetails = [{'emailId': 'vik@g.com','name':'Alision', 'subject':'hello'},{'emailId':'sri@y.com','name':'Hanumant', 'subject':'ola'},
                           {'emailId':'ally@o.com','name':'Brian', 'subject':'namaste'},{'emailId':'vik@g.com','name':'Alision', 'subject':'hello'}]

There can be multiple entries with same emailId.

So what I want to do is replace key i.e. emailId from emailCount with name from emailDetails.

Name for emailId in emailDetails, irrespective of how many entries will always remain same.

My expected O/P is : {'Alision':4,'Hanumant': 9}

How can I replace my key in emailCount with name in emailDetails' emailId as key?I tried looking solutions but was unable to find aything replated to it. If any one needs any furteher detais please let me.

Siva Pradhan
  • 791
  • 1
  • 6
  • 23

5 Answers5

2

Basically if you want to group it and count it, You can use Array.reduce

var groupByCount = (arrayData, key) => {
    return arrayData.reduce( (r, a) => {
        r[a[key]] = r[a[key]] || 0 ;
        r[a[key]] ++;
        return r;
    }, Object.create(null));

}

Use

const emailDetails = [{'emailId': 'vik@g.com','name':'Alision', 'subject':'hello'},{'emailId':'sri@y.com','name':'Hanumant', 'subject':'ola'},
                           {'emailId':'ally@o.com','name':'Brian', 'subject':'namaste'},{'emailId':'vik@g.com','name':'Alision', 'subject':'hello'}]


groupByCount(emailDetails, 'name'); // {Alision: 2, Hanumant: 1, Brian: 1}

groupByCount(emailDetails, 'emailId'); // {vik@g.com: 2, sri@y.com: 1, ally@o.com: 1}
 
groupByCount(emailDetails, 'subject'); // {hello: 2, ola: 1, namaste: 1}

Dipak Telangre
  • 1,792
  • 4
  • 19
  • 46
  • 1
    Great answer, this is so far the only one that avoids [prototype pollution](https://github.com/Kirill89/prototype-pollution-explained). – Patrick Roberts Apr 22 '21 at 06:25
1

I threw together a quick example with comments that explain what is going on as it's moving through the script.

const emailCount = {'vik@g.com':4,'sri@y.com':9}

const emailDetails = [
  {'emailId': 'vik@g.com','name':'Alision', 'subject':'hello'},
  {'emailId':'sri@y.com','name':'Hanumant', 'subject':'ola'},
  {'emailId':'ally@o.com','name':'Brian', 'subject':'namaste'},
  {'emailId':'vik@g.com','name':'Alision', 'subject':'hello'}
]

// Create the object that we're going to store the output in
const output = {}

// Loop through the emailCount object in [[email, count]] format
Object.entries(emailCount)
  .forEach((emailCountEntry) => {
    const [email, count] = emailCountEntry
    
    // Filter through our second input object and return any entries that match the given email
    const selected = emailDetails.filter(details => details.emailId === email)
    
    // If one was found, add it to our output
    if (selected.length) {
      output[selected[0].name] = count
    }
  })
  
console.log(output)

In the future, please try to include anything you've already tried along with your code in the question. It helps to show that you've put in effort in trying to solve your problem before posting it here.

Chase Ingebritson
  • 1,559
  • 1
  • 12
  • 25
1
const output = {};
Object.entries(emailCount).forEach(([key, value]) => {
    output[emailDetails.find(item => item.emailId === key).name] = value;
})

note : no undefined check has been done yet, this code needs to be fine-tuned, but here is the general idea

JSFiddle : https://jsfiddle.net/L0o4x86e/

vicovicovico
  • 358
  • 1
  • 4
  • 16
1

If I understand correctly, you only want to replace emailCount's keys, not create another object or do any extra counting.

If so, you can mutate the emailCount object:

const emailCount = {'vik@g.com': 4, 'sri@y.com': 9}
const emailDetails = [{'emailId': 'vik@g.com', 'name': 'Alision', 'subject': 'hello'}, {'emailId': 'sri@y.com', 'name': 'Hanumant', 'subject': 'ola'}, {'emailId': 'ally@o.com', 'name': 'Brian', 'subject': 'namaste'}, {'emailId': 'vik@g.com', 'name': 'Alision', 'subject': 'hello'}]

for (emailId in emailCount) {
    const name = emailDetails.find(x => x.emailId === emailId).name
    delete Object.assign(emailCount, {[name]: emailCount[emailId]})[emailId]
}

console.log(emailCount)
tdy
  • 36,675
  • 19
  • 86
  • 83
1
emailDetails.forEach(function(detail) {
  if(emailCount[detail.emailId]) {
    emailCount[detail.name] = emailCount[detail.emailId];
    delete emailCount[detail.emailId];
  }
 });

A simple solution using a single loop. If a match is found in emailCount object for that emailId, copy that in a new key and delete the email key.

Nikhilesh K V
  • 1,480
  • 13
  • 20