0

I have an array of objects, it looks like this:

[{
    Rank: 1,
    Speed1: 91,
    Speed2: 457,
    Username: 'monizotic',
    ProfileLink: 'profile_link',
    VerifiedSpeed: null,
    Video: null
}, {
    Rank: 2,
    Speed1: 91,
    Speed2: 457,
    Username: 'Thachtawan',
    ProfileLink: 'profile_link',
    VerifiedSpeed: null,
    Video: null
}, {
    Rank: 3,
    Speed1: 91,
    Speed2: 456,
    Username: 'PassornSibpang',
    ProfileLink: 'profile_link',
    VerifiedSpeed: null,
    Video: null
}, {
    Rank: 4,
    Speed1: 91,
    Speed2: 456,
    Username: 'WasinSoikeeree',
    ProfileLink: 'profile_link',
    VerifiedSpeed: null,
    Video: null
}, {
    Rank: 5,
    Speed1: 91,
    Speed2: 454,
    Username: 'user1055644',
    ProfileLink: 'profile_link',
    VerifiedSpeed: null,
    Video: null
}]

Each object is "1 user". Rank is the user's place in the leaderboard. Each user also has Speed1 and Speed2. Whoever has the highest Speed1 and Speed2 is in the first place. Those who have the lowest ones are on the last place. I hope you understand the meaning. I need to somehow implement a function that would be able to insert a "new user" into this array with objects. An example of such a user:

{
    Rank: null,
    Speed1: 91,
    Speed2: 456,
    Username: 'thaniman',
    ProfileLink: 'profile_link',
    VerifiedSpeed: null,
    Video: null
}

In the object above Rank is null, since it is not yet known. It should change when this user object is in the right place in the array

How can I do that?

3
  • John, are you sure it's an array the [] square brackets are missing Commented Jul 3, 2022 at 13:16
  • What code have you attempted to solve this riddle? You should add that to your question. Commented Jul 3, 2022 at 13:16
  • 1
    @fuzzybear now it's okay Commented Jul 3, 2022 at 13:18

2 Answers 2

2

Please see the below solution with an O(N) time complexity.

It was made with an assumption that the desired insertion index logic is (user.Speed1 * user.Speed2) < (newUser.Speed1 * newUser.Speed2). Consequently, among all users with identical speeds, the new user will be inserted as the last one.

Noteworthy, though, the users may be not-the-best data structure for this task.

const users = [
 { Rank: 1, Speed1: 91, Speed2: 457, Username: 'monizotic',      ProfileLink: 'profile_link', VerifiedSpeed: null, Video: null },
 { Rank: 2, Speed1: 91, Speed2: 457, Username: 'Thachtawan',     ProfileLink: 'profile_link', VerifiedSpeed: null, Video: null },
 { Rank: 3, Speed1: 91, Speed2: 456, Username: 'PassornSibpang', ProfileLink: 'profile_link', VerifiedSpeed: null, Video: null },
 { Rank: 4, Speed1: 91, Speed2: 456, Username: 'WasinSoikeeree', ProfileLink: 'profile_link', VerifiedSpeed: null, Video: null },
 { Rank: 5, Speed1: 91, Speed2: 454, Username: 'user1055644',    ProfileLink: 'profile_link', VerifiedSpeed: null, Video: null }
];


const insertUser = newUser => {
  const newUserSpeed = newUser.Speed1 * newUser.Speed2;
  let insertIndex = users.findIndex(user => (user.Speed1 * user.Speed2) < newUserSpeed);
      insertIndex = insertIndex >= 0 ? insertIndex : users.length;

  // assign the new user a rank
  newUser.Rank = insertIndex + 1; 

  // insert the user
  users.splice(insertIndex, 0, newUser);

  // increment ranks of subsequent users
  users.slice(insertIndex + 1).forEach(user => user.Rank++);
};

insertUser({ Rank: null, Speed1: 91, Speed2: 456, Username: 'thaniman', ProfileLink: 'profile_link', VerifiedSpeed: null, Video: null });
console.log(JSON.stringify(users))

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the answer, but I don't understand a bit about "new user needs to be inserted based on the sum of the two speeds". Like I said in the question description, I'm targeting both speeds. The user with the highest Speed1 and Speed2 scores gets first place. The user with the lowest Speed1 and Speed2 scores comes in last place. Here is an example of what l-rd might look like: 1. Speed1: 94, Speed2: 180 2. Speed1: 94, Speed2: 179 3. Speed1: 94, Speed2: 179 4. Speed1: 94, Speed2: 178 5. Speed1: 93, Speed: 180 If you wrote the code based on the above, then everything is fine.
@John, If the desired order is like in the following example, the updated code matches this expectation. 4. Speed1: 94, Speed2: 178 5. Speed1: 93, Speed: 180
0

It's probably best to do this in stages rather than all at once.

  1. push the new user object into the data array.
  2. map over each user object and calculate the average speed.
  3. sort the returned array by average speed.
  4. map over the sorted array updating the rank for each user based on the object's position in the array.

const data=[{Rank:1,Speed1:91,Speed2:457,Username:"monizotic",ProfileLink:"profile_link",VerifiedSpeed:null,Video:null},{Rank:2,Speed1:91,Speed2:457,Username:"Thachtawan",ProfileLink:"profile_link",VerifiedSpeed:null,Video:null},{Rank:3,Speed1:91,Speed2:456,Username:"PassornSibpang",ProfileLink:"profile_link",VerifiedSpeed:null,Video:null},{Rank:4,Speed1:91,Speed2:456,Username:"WasinSoikeeree",ProfileLink:"profile_link",VerifiedSpeed:null,Video:null},{Rank:5,Speed1:91,Speed2:454,Username:"user1055644",ProfileLink:"profile_link",VerifiedSpeed:null,Video:null}];
const newUser={Rank:null,Speed1:91,Speed2:456,Username:"thaniman",ProfileLink:"profile_link",VerifiedSpeed:null,Video:null};

// `push` the new user into the array
data.push(newUser);

// `map` over the array to create some average speeds
const average = data.map(obj => {
  return { ...obj, Avg: (obj.Speed1 + obj.Speed2) / 2 };
});

// `sort` the array by those averages
average.sort((a, b) => b.Avg - a.Avg);

// `map` over the objects and update the rank
// based on the object's position in the array
const final = average.map((obj, i) => {
  const { Rank, Avg, ...rest } = obj;
  return { ...rest, Rank: i + 1 };
});

console.log(final);

4 Comments

Changing the references might break other parts that access the objects which are not shown in the example. You really suggest creating new objects all over again? Assigning the Rank and Avg would be enough.
Thank you very much, but I need to make sure that the final array with the objects does not have an Avg property. I need to keep Speed1 and Speed2. Also, Speed1 and Speed2 should only be integers, not fractions.
Sorry @John, didn't' realise I missed those out - answer updated. And Christopher, I like this solution.
@Andy you still create a new reference in the last mapping. Just assign the value to obj.Rank instead of creating a new object. Also you can store the the value in a temp object like: { avg: ..., obj } on the first map and return newObj.obj on the final map. This will keep the reference and removes the issue with a new property.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.