0

I am building a rating component and wish to associate a rating with a message (pulled from an array of messages). The messages array and rating are dynamic, so there is potential for unequal subrange associations.

Example:

ratingRange = 10; //So 1-10 rating potential
messagesArray = ['Bad', 'Okay', 'Good', 'Amazing']; //This array can be of any length but will never be greater than the maxRating
currentRating = 4;

By the above example:

currentRating [1-3] = messages[0] //('Bad')
currentRating [4-6] = messages[1] //('Okay')
currentRating [7-8] = messages[2] //('Good')
currentRating [9-10] = messages[3] //('Amazing')

Rating of 4 would equate to the message 'Okay'.

Assuming that the messagesArray and ratings are relationally sorted already, the Fn would look like:

function getMessageByRating(
  ratingRange: number,
  messagesArray: string[],
  currentRating: number
) {

}

Optimal tests getMessageByRating(ratingRange, messageArray, currentRating):

getMessageByRating(5, ['Bad', 'Okay', 'Good'], 2) //Bad
getMessageByRating(5, ['Bad', 'Okay', 'Good'], 4) //Okay
getMessageByRating(5, ['Bad', 'Okay', 'Good'], 5) //Good

getMessageByRating(10, ['Bad', 'Okay', 'Good'], 4) //Bad
getMessageByRating(10, ['Bad', 'Okay', 'Good'], 5) //Okay
getMessageByRating(10, ['Bad', 'Okay', 'Good'], 7) //Okay
getMessageByRating(10, ['Bad', 'Okay', 'Good'], 8) //Good

getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 3) //Bad
getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 4) //Okay
getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 6) //Okay
getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 7) //Good
getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 8) //Good
getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 9) //Amazing

Answers like Split array into chunks tend to split the chunks by chunk length and do not have a more uniform distribution between them.

CoJanks
  • 109
  • 1
  • 1
  • 9

1 Answers1

1

When the number of labels cannot be split evenly, it looks like you want to first allocate the larger groups and then the smaller groups, meaning that the first label(s) may each have one more rating point mapped to them than the label(s) at the end.

The number of larger groups (with room for one more rating point) is equal to the remainder you get from dividing the rating range by the number of labels.

You can then apply a formula that depends on whether the given rating belongs to a large or small group:

function getMessageByRating(ratingRange, messagesArray, currentRating) {
    const numLargeGroups = ratingRange % messagesArray.length;
    const smallSize = (ratingRange - numLargeGroups) / messagesArray.length;
    const split = numLargeGroups * (smallSize + 1);
    // Make currentRating zero-based and see if it belongs in smaller or larger group
    return --currentRating >= split 
            ? messagesArray[numLargeGroups + Math.floor((currentRating - split) / smallSize)]
            : messagesArray[Math.floor(currentRating / (smallSize + 1))];
}

console.log(getMessageByRating(5, ['Bad', 'Okay', 'Good'], 2)) //Bad
console.log(getMessageByRating(5, ['Bad', 'Okay', 'Good'], 4)) //Okay
console.log(getMessageByRating(5, ['Bad', 'Okay', 'Good'], 5)) //Good
console.log("-----");
console.log(getMessageByRating(10, ['Bad', 'Okay', 'Good'], 4)) //Bad
console.log(getMessageByRating(10, ['Bad', 'Okay', 'Good'], 5)) //Okay
console.log(getMessageByRating(10, ['Bad', 'Okay', 'Good'], 7)) //Okay
console.log(getMessageByRating(10, ['Bad', 'Okay', 'Good'], 8)) //Good
console.log("-----");
console.log(getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 3)) //Bad
console.log(getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 4)) //Okay
console.log(getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 6)) //Okay
console.log(getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 7)) //Good
console.log(getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 8)) //Good
console.log(getMessageByRating(10, ['Bad', 'Okay', 'Good', 'Amazing'], 9)) //Amazing
trincot
  • 317,000
  • 35
  • 244
  • 286
  • What would you call this kind of splitting? I had such a hard time trying to think of the keywords to search for when I was researching for this answer – CoJanks Aug 15 '23 at 17:23
  • I have no idea how you would call this kind of splitting *specifically*, but more generally it has to do with *evenly splitting an array into chunks*. – trincot Aug 15 '23 at 17:31