简体   繁体   中英

How to loop through objects and count unique values of key?

I have logs of json files which are objects that look like

{
  "logs": [
    {
      "id": "12321321321321",
      "email": "test@email.com",
      "message": "ahahaha"
    },
    {
      "id": "12321321312",
      "email": "test@email.com",
      "message": "hahahaha."
    },
   "id": "12321321321"
}

I need to return a new object that contains

{
    "hello_id": outer id of the json file,
    "array": [
       
       {
        "email": "test@me.com",
        "total": 2
       }
      ]
    }

So far I am looping through the json files and have

    jsonsInDirectory.forEach((file) => {
  const fileData = fs.readFileSync(path.join("./logs", file), "utf8");
  const jsonData = JSON.parse(fileData);
  }
});

The key is "logs" and "id" and the values are the objects in the "logs" and the value of "id"

How can I count and return a new object at the same time?

You can try this approach: make a hash object that counts emails. Then just map it to an array of objects.

 const data = { logs: [{ id: "89004ef9-e825-4547-a83a-c9e9429e8f95", email: "noah.sanchez@me.com", message: "successfully handled skipped operation." }, { id: "89004ef9-e825-4547-a83a-c9e9429e8f95", email: "noah.sanchez@me.com", message: "successfully handled skipped operation." }, { id: "89004ef9-e825-4547-a83a-c9e9429e8f95", email: "noname@me.com", message: "successfully handled skipped operation." }], id: "56f83bed-3705-4115-9067-73930cbecbc0", }; const emails = data.logs.reduce((acc, { email }) => { acc[email] = (acc[email]?? 0) + 1; return acc; }, {}); const tally = Object.entries(emails).map(([email, total]) => ({ email, total })); const result = { logs_id: data.id, tally }; console.log(result)
 .as-console-wrapper { max-height: 100%;important: top 0 }

When you do const jsonData = JSON.parse(fileData); , you get the file data as a JSON and knowing the struct of that JSON you can easily get the info.

I have created a example https://codesandbox.io/s/stackoverflow-logs-count-example-jys2vg?file=/src/index.js

It may not solve exactly wath you want.

To solve this problem with the most time efficiency, you can create a tally object by firstly creating a map of the occurences of each mail with the email as the key and no of occurences as the value, since this will take constant (O(1)) time to execute, afterwhich you can create the tally array from the map as given below

output = []
jsonsInDirectory.forEach((file) => {
  const fileData = fs.readFileSync(path.join("./logs", file), "utf8");
  const jsonData = JSON.parse(fileData);
  var map = {}
  jsonData.logs.forEach((log) => {
    if(log.email in map){
        map[log.email] += 1
    }
    else {
        map[log.email] = 1
    }
  });
  var tally = []
  for(var email in map){
    tally.push({email: email, total: map[email]})
  }
  output.push({logs_id: jsonData['id'], tally: tally});
})

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