2

Alright, so I have an array of objects that includes null values for a certain property.

The object looks roughly like this for sorting purposes... (40 elements, but this will suffice...).

It needs to be sorted based on roulette descending (with roulette sometimes being null), then novelty, then popularity.

My head is getting a bit crushed.

This works to sort the roulette in descending, but how do I need to extend it to include the other two criteria?

Object:

[
 {
  title: 'one',
  popularity: 4,
  novelty: 3
 },
 {
  title: 'two',
  popularity: 1
  novelty: 4
 },
 {
  title: 'three',
  popularity: 5,
  novelty: 3,
  roulette: 0
 },
 {
  title: 'four',
  popularity: 5,
  novelty: 3,
  roulette: 1
 }
]

Partially working function:

  object.sort(function(a, b) {
    if (a['roulette'] == null) return 1
    if (b['roulette'] == null) return -1
    if (a['roulette'] === b['roulette']) return 0
    return b.roulette > a.roulette ? 1 : -1
  });
6
  • please add some more data and the wanted result. i am sorry i can not read what novelty means in sorting. Commented Nov 11, 2016 at 7:04
  • @NinaScholz novelty is an attrbute in his json. Commented Nov 11, 2016 at 7:04
  • yes, i read this, but where should null go? Commented Nov 11, 2016 at 7:05
  • @NinaScholz according to his partial sort function null values will come at bottom. Commented Nov 11, 2016 at 7:06
  • are there null values in roulette or is roulette just not set? Commented Nov 11, 2016 at 7:23

5 Answers 5

3

An attempt with sorting with priority and groups.

var data = [{ title: 'one', popularity: 4, novelty: 3 }, { title: 'two', popularity: 1, novelty: 4 }, { title: 'three', popularity: 5, novelty: 3, roulette: 0 }, { title: 'four', popularity: 5, novelty: 3, roulette: 1 }, { title: 'five', popularity: 5, novelty: 4, roulette: null }, { title: 'six', popularity: 5, novelty: 5, roulette: undefined }];

data.sort(function (a, b) {
    return (
        (a.roulette === undefined || a.roulette === null) - (b.roulette === undefined || b.roulette === null) ||
        a.roulette - b.roulette ||
        a.novelty - b.novelty ||
        a.popularity - b.popularity
    );       
});

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

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

4 Comments

Shouldn't the bs be on the left? Otherwise, that's a pretty slick solution.
Both 'roulette' in {roulette:null} and 'roulette' in {roulette:undefined} are true so those will always come out true unless roulette hasn't been set at all.
it not clear from the data, if it is set with null or undefined, not at all inside of the object.
This is like... 99.9% there. There is a minor side effect for the first undefined/null data point, but it's minor enough for me not to care. I needed biggest on top, so slight mod: return ( (a.roulette === undefined || a.roulette === null) - (b.roulette === undefined || b.roulette === null) || b.roulette - a.roulette || b.novelty - a.novelty || b.popularity - a.popularity );
1

Here is the preferential sorting (descending) with roulette, novelty and popularity (in that order)

This handles both null and undefined - check out the demo below:

var object=[{title:"one",popularity:4,novelty:3},{title:"two",popularity:1,novelty:4},{title:"three",popularity:5,novelty:3,roulette:0},{title:"four",popularity:5,novelty:3,roulette:1},{title:"five",roulette:4,novelty:null},{title:"six",popuplarity:7},{title:"seven",novelty:8,roulette:null},{title:"eight",novelty:0},{title:"nine",popularity:10}];

function ifNumber(num) {
  if(num == undefined || num == null)
    return -Infinity;
  else
    return num;
}

var result = object.sort(function(a, b) {
  return (ifNumber(b.roulette) - ifNumber(a.roulette)) 
      || (ifNumber(b.novelty) - ifNumber(a.novelty))
      || (ifNumber(b.popuplarity) - ifNumber(a.popuplarity));
});
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}

Comments

0

You can try sorting based on weighted rank:

var data=[{title:"one",popularity:4,novelty:3},{title:"two",popularity:1,novelty:4},{title:"three",popularity:5,novelty:3,roulette:0},{title:"four",popularity:5,novelty:3,roulette:1}];

data.sort(function(a, b) {
  var r1 = a.roulette === undefined ? -1 : a.roulette;
  var r2 = b.roulette === undefined ? -1 : b.roulette;
  var n1 = a.novelty === undefined ? -1 : a.novelty;
  var n2 = b.novelty === undefined ? -1 : b.novelty;
  var p1 = a.popularity === undefined ? -1 : a.popularity;
  var p2 = b.popularity === undefined ? -1 : b.popularity;

  var r_rank = r1 > r2 ? -100 : r1 < r2 ? 100 : 0;
  var n_rank = n1 > n2 ? -10 : n1 < n2 ? 10 : 0;
  var p_rank = p1 > p2 ? -1 : p1 < p2 ? 1 : 0;

  return r_rank + n_rank + p_rank;
})

var r_rank = r1 > r2 ? -100 : r1 < r2 ? 100 : 0;
var n_rank = n1 > n2 ? -10 : n1 < n2 ? 10 : 0;
var p_rank = p1 > p2 ? -1 : p1 < p2 ? 1 : 0;
return r_rank + n_rank + p_rank;
})

console.log(data)

Comments

0

Just include more conditionals:

var data = [{"title":"one","popularity":4,"novelty":3},{"title":"two","popularity":1,"novelty":4},{"title":"three","popularity":5,"novelty":3,"roulette":0},{"title":"four","popularity":5,"novelty":3,"roulette":1}];
data.sort(function(a,b) {
  if (a.roulette < b.roulette || a.roulette == null) return +1;
  if (a.roulette > b.roulette || b.roulette == null) return -1;
  if (a.novelty < b.novelty || a.novelty == null) return +1;
  if (a.novelty > b.novelty || b.novelty == null) return -1;
  if (a.popularity < b.popularity || a.popularity == null) return +1;
  if (a.popularity > b.popularity || b.popularity == null) return -1;
  return 0;
})
console.log(data);

1 Comment

Maybe something like a.roulette < b.roulette || a.roulette == null && b.roulette != null or (a.roulette != null ? a.roulette : -Infinity) < b.roulette would be more appropriate.
0

You just have to keep on breaking ties if one parameter is same.

 obj.sort(function(a, b) {
    var rouletteDiff = compare(a.roulette, b.roulette);
    if(rouletteDiff != 0) return rouletteDiff;
    var noveltyDiff = compare(a.novelty, b.novelty);
    if(noveltyDiff != 0) return noveltyDiff;
    return compare(a.popularity, b.popularity);
  });

  function compare(x,y){
    if(x == undefined) return 1;
    if(y == undefined) return -1;
    if(x === y){
        return 0;
    }else{
        return x > y ? -1 : 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.