Finding best time from users usin JSON array

Viewed 56

I am trying to find the best result for each user from JSON.

const users = [
    {
        "key": "user1",
        "label": "Henry"
    },
    {
        "key": "user2",
        "label": "Michael"
    },
    {
        "key": "user3",
        "label": "Fiddel"
    },
    {
        "key": "user4",
        "label": "Alex"
    },
    {
        "key": "user5",
        "label": "Mark"
    }
]


const results = [
    {
        "user1": "00:31.241",
        "user2": "00:30.945",
        "user3": "00:33.065",
        "user4": null,
        "user5": null
    },
    {
        "user1": "00:28.963",
        "user2": "00:31.657",
        "user3": "00:28.504",
        "user4": null,
        "user5": null
    },
    {
        "user1": "00:26.956",
        "user2": "00:26.416",
        "user3": "00:27.328",
        "user4": "00:29.904",
        "user5": null
    },
    {
        "user1": "00:31.889",
        "user2": "00:32.739",
        "user3": "01:00.515",
        "user4": "00:28.336",
        "user5": "00:35.745"
    },
    {
        "user1": "00:26.470",
        "user2": "00:30.063",
        "user3": "00:28.696",
        "user4": "00:30.248",
        "user5": "00:35.123"
    },
    {
        "user1": "00:26.956",
        "user2": "00:33.588",
        "user3": "00:30.021",
        "user4": "00:29.154",
        "user5": "00:38.492"
    },
    {
        "user1": "00:27.190",
        "user2": "00:32.307",
        "user3": "00:30.467",
        "user4": "00:30.189",
        "user5": "00:39.669"
    },
    {
        "user1": "00:27.368",
        "user2": "00:28.124",
        "user3": "00:29.960",
        "user4": "00:29.649",
        "user5": "00:42.450"
    },
    {
        "user1": "00:28.429",
        "user2": "00:27.651",
        "user3": "00:28.260",
        "user4": "00:30.077",
        "user5": "00:48.992"
    },
    {
        "user1": "00:29.425",
        "user2": "00:31.142",
        "user3": "00:40.343",
        "user4": "00:29.897",
        "user5": "00:42.552"
    }
]

So far I have came up with following solution:

let array = [];
 
const bestTime = results.map(Object.entries).flat().sort((a, b) => a[1] ?.localeCompare(b[1]))[0];

array = [users.filter(user => user.key === test[0])[0].label, test[1]]

Problem is that I can't figure out how to print out an array with the best result for each user instead of just one. I would like to have an output like: [{name: 'Henry', value: 00:35.233}, {name: 'Michael', value: 00.27.333}, etc]

Now I am trying to get sum of all values for each user, I figured out how to filter out null values from JSON and how to get sum of all values. Problem is that results are string values and i cant figure out how to parse that data correctly to get sum.

const final = users.map(({ label, key }) => ({

    name: label,
    value: results.map(r => r[key]).filter(el => el != null).reduce((prev, curr) => parseInt(prev) + parseInt(prev);


}));
2 Answers

First iterate over the results and combine each user# property value into an array for that user. Then you can sort it, create an object mapping user#s to names, and take the first value in the sorted array to get what you want:

const users=[{key:"user1",label:"Henry"},{key:"user2",label:"Michael"},{key:"user3",label:"Fiddel"},{key:"user4",label:"Alex"},{key:"user5",label:"Inga"}],results=[{user1:"00:31.241",user2:"00:30.945",user3:"00:33.065",user4:null,user5:null},{user1:"00:28.963",user2:"00:31.657",user3:"00:28.504",user4:null,user5:null},{user1:"00:26.956",user2:"00:26.416",user3:"00:27.328",user4:"00:29.904",user5:null},{user1:"00:31.889",user2:"00:32.739",user3:"01:00.515",user4:"00:28.336",user5:"00:35.745"},{user1:"00:26.470",user2:"00:30.063",user3:"00:28.696",user4:"00:30.248",user5:"00:35.123"},{user1:"00:26.956",user2:"00:33.588",user3:"00:30.021",user4:"00:29.154",user5:"00:38.492"},{user1:"00:27.190",user2:"00:32.307",user3:"00:30.467",user4:"00:30.189",user5:"00:39.669"},{user1:"00:27.368",user2:"00:28.124",user3:"00:29.960",user4:"00:29.649",user5:"00:42.450"},{user1:"00:28.429",user2:"00:27.651",user3:"00:28.260",user4:"00:30.077",user5:"00:48.992"},{user1:"00:29.425",user2:"00:31.142",user3:"00:40.343",user4:"00:29.897",user5:"00:42.552"}];

const timesByUserNumber = {};
for (const result of results) {
  for (const [userNumber, time] of Object.entries(result)) {
    if (!timesByUserNumber[userNumber]) {
      timesByUserNumber[userNumber] = [];
    }
    if (time) {
      // Exclude nulls:
      timesByUserNumber[userNumber].push(time);
    }
  }
}
for (const arr of Object.values(timesByUserNumber)) {
  arr.sort((a, b) => a.localeCompare(b));
}
const userLabelsByUserNumber = Object.fromEntries(
  users.map(({ key, label }) => [key, label])
);
const output = Object.entries(timesByUserNumber)
  .map(([userNumber, timeArr]) => ({
    name: userLabelsByUserNumber[userNumber],
    value: timeArr[0]
  }));
console.log(output);

You could also "sort" by comparing each item individually while iterating:

const users=[{key:"user1",label:"Henry"},{key:"user2",label:"Michael"},{key:"user3",label:"Fiddel"},{key:"user4",label:"Alex"},{key:"user5",label:"Inga"}],results=[{user1:"00:31.241",user2:"00:30.945",user3:"00:33.065",user4:null,user5:null},{user1:"00:28.963",user2:"00:31.657",user3:"00:28.504",user4:null,user5:null},{user1:"00:26.956",user2:"00:26.416",user3:"00:27.328",user4:"00:29.904",user5:null},{user1:"00:31.889",user2:"00:32.739",user3:"01:00.515",user4:"00:28.336",user5:"00:35.745"},{user1:"00:26.470",user2:"00:30.063",user3:"00:28.696",user4:"00:30.248",user5:"00:35.123"},{user1:"00:26.956",user2:"00:33.588",user3:"00:30.021",user4:"00:29.154",user5:"00:38.492"},{user1:"00:27.190",user2:"00:32.307",user3:"00:30.467",user4:"00:30.189",user5:"00:39.669"},{user1:"00:27.368",user2:"00:28.124",user3:"00:29.960",user4:"00:29.649",user5:"00:42.450"},{user1:"00:28.429",user2:"00:27.651",user3:"00:28.260",user4:"00:30.077",user5:"00:48.992"},{user1:"00:29.425",user2:"00:31.142",user3:"00:40.343",user4:"00:29.897",user5:"00:42.552"}];

const userLabelsByUserNumber = Object.fromEntries(
  users.map(({ key, label }) => [key, label])
);
const grouped = {};
for (const result of results) {
  for (const [userNumber, time] of Object.entries(result)) {
    if (!time) continue;
    const name = userLabelsByUserNumber[userNumber];
    if (!grouped[name]) {
      grouped[name] = { name, value: time };
    } else if (grouped[name].value.localeCompare(time) > 0) {
      grouped[name].value = time;
    }
  }
}
console.log(Object.values(grouped));

I made out a solution by sorting the time values with .localeCompare() and getting the first element from the result array. But before using .map() on the results array and listing the times by its key properties inside an another .map() for each users.

See a working example below:

const users = [{"key": "user1","label": "Henry"},{"key": "user2","label":"Michael"},{"key": "user3","label": "Fiddel"},{"key": "user4","label": "Alex"},{"key": "user5","label": "Inga"}]
const results = [{"user1": "00:31.241","user2": "00:30.945","user3": "00:33.065","user4": null,"user5": null},{"user1": "00:28.963","user2": "00:31.657","user3": "00:28.504","user4": null,"user5": null},{"user1": "00:26.956","user2": "00:26.416","user3": "00:27.328","user4": "00:29.904","user5": null},{"user1": "00:31.889","user2": "00:32.739","user3": "01:00.515","user4": "00:28.336","user5": "00:35.745"},{"user1": "00:26.470","user2": "00:30.063","user3": "00:28.696","user4": "00:30.248","user5": "00:35.123"},{"user1": "00:26.956","user2": "00:33.588","user3": "00:30.021","user4": "00:29.154","user5": "00:38.492"},{"user1": "00:27.190","user2": "00:32.307","user3": "00:30.467","user4": "00:30.189","user5": "00:39.669"},{"user1": "00:27.368","user2": "00:28.124","user3": "00:29.960","user4": "00:29.649","user5": "00:42.450"},{"user1": "00:28.429","user2": "00:27.651","user3": "00:28.260","user4": "00:30.077","user5": "00:48.992"},{"user1": "00:29.425","user2": "00:31.142","user3": "00:40.343","user4": "00:29.897","user5": "00:42.552"}]
    
const bestTimes = users.map(({label, key}) => ({
   name: label,
   value: results.map(r => r[key])
                 .sort((a, b) => 
                     a === null && b === null ?
                       -1 :
                       a.localeCompare(b))[0]
}))

console.log(bestTimes)

Related