2

Assume I have an array of options to sort by multiple scores, and those scores are an array of variable length

[
  #[Label, scores]
  ["Label6", [1]
  ["Label5", [1,5]
  ["Label2", [0,1,3,5],
  ["Label1", [0,1,2]
  ["Label3", [0,1,4],
  ["Label4", [1,4]
]

I want to sort this list by evaluating array elements one by one. IE. I will first sort (ascending) by the score[0], then score[i+1] if it exists, etc. When score[i] does not exist, it should be considered as an infinite value (appear at the bottom)

This could gives the following output on the previous data :

list = [
  #[Label, scores]
  ["Label1", [0,1,2]  
  ["Label2", [0,1,3,5],
  ["Label3", [0,1,4],
  ["Label4", [1,4]
  ["Label5", [1,5]
  ["Label6", [1]
]

How can I write this function ? Is there a native/ES6 (or lodash/underscore) sortBy() function like we have in other languages ? (for example in Ruby you would simply list.sort_by(&:last) to get this effect). Or does it need to be implemented manually ?

8
  • 1
    Take a look at the Array.prototype.sort function. Commented Oct 30, 2019 at 12:20
  • @Kobe I'm can't see any example of what I'm trying to achieve in the doc of the .sort function. All solutions I came across involved something like sort((a,b) => if a[0] - b[0], a[1] - b[1], ... but what happens when an "item of sort criteria" can be of variable length ? Commented Oct 30, 2019 at 12:23
  • Then you'd write the callback function accordingly. I'll start on an answer now, but it seems quite difficult Commented Oct 30, 2019 at 12:24
  • I could convert scores to a string, then join them and just perform an alphabetical sort... but then I'd be dead if my scores were higher than 9 and that could be the case. Commented Oct 30, 2019 at 12:25
  • So you want 0, 1, 2 to appear after 0, 1, 2, 3? Commented Oct 30, 2019 at 12:28

2 Answers 2

5

You could take the arrays, and sort by same index values.

At start take the minimum length of both arrays as the length for iterating the values and to prevent to take undefined.

If the delta of two values of same index is not zero, return the delta, otherwise proceed with the next index.

If all indices are visited without a former return, all value at the same index are equal until the minimum length of both arrays. In this case return the delta of the length of both in switched order, because the longer array should come first.

var array = [["Label6", [1, 5]], ["Label2", [0, 1, 3, 5]], ["Label1", [0, 1, 2]], ["Label3", [0, 1, 4]], ["Label5", [1, 5, 2]], ["Label4", [1, 4]]];

array.sort(([, a], [, b]) => {
    var delta,
        index = 0,
        length = Math.min(a.length, b.length);

    while (index < length) {
        delta = a[index] - b[index];
        if (delta) return delta;
        index++;
    }

    return b.length - a.length;
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

Comments

0

There is the array.sort() function, which takes in a sorting algorithm and sorts the array for you based on that. all you have to do is implement the sorting for only 2 arguments.

here is what i'd do in your case:

list.sort( list1, list2 => {
  let i = 0, iterations = min(list1.length, list2.length);
  for( i = 0; i<iterations; i++ ){
    if( list1[i] < list2[i] ) return -1;
    if( list1[i] > list2[i] ) return 1;
  }
  if( list1.length === list2.length ) return 0;
  if( i === list1.length ) return -1;
  if( i === list2.length ) return 1;
}

Comments

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.