1

I have a variable and array of objects e.g:

var selectedName = 'fff';

[{
    percentage: Math.round(percentage),
    count: count,
    name: 'bbb',
    index: 11,
},
{
    percentage: Math.round(percentage),
    count: 200,
    name: 'aaa',
    index: 2,
},
{
    percentage: Math.round(percentage),
    count: 400,
    name: 'All',
    index: 7,
},
{
    percentage: Math.round(percentage),
    count: count,
    name: 'fff',
    index: 8,
},
{
    percentage: Math.round(percentage),
    count: count,
    name: 'ccc',
    index: 3,
}],

I want to sort these as follows: the object which has the name 'All' should always be first. The next object should be the one with the name that matches selectedName, in this case 'fff'. And then the rest of the objects should be ordered by ascending order of their 'index' property.

Is this possible in one Array.sort() method?

1
  • arr.sort(compareFunction) - Look under the Description heading on that page you linked to for examples of compareFunction. Commented Mar 23, 2017 at 12:30

4 Answers 4

4

Yes, here an example:

var selectedName = 'fff';
let percentage = 1;
let count = 2;
var data=[{percentage:Math.round(percentage),count:count,name:"bbb",index:11},{percentage:Math.round(percentage),count:200,name:"aaa",index:2},{percentage:Math.round(percentage),count:400,name:"All",index:7},{percentage:Math.round(percentage),count:count,name:"fff",index:8},{percentage:Math.round(percentage),count:count,name:"ccc",index:3}];

arr.sort((i, j) => {
    if (i.name === j.name && (i.name === 'All' || i.name === selectedName)) return 0;

    if (i.name === 'All') return -1;
    if (j.name === 'All') return 1;
    
    if (i.name === selectedName) return -1;
    if (j.name === selectedName) return 1;
    
    if (i.index < j.index) return -1;
    if (i.index > j.index) return 1;
    return 0;
})

console.log(arr)

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

1 Comment

Have minified input data so that emphasis is on your code.
1

Sure you can do it like so:

var selectedName = 'fff';
var percentage = 23;
var count = 3;

var data=[{percentage:Math.round(percentage),count:count,name:"bbb",index:11},{percentage:Math.round(percentage),count:200,name:"aaa",index:2},{percentage:Math.round(percentage),count:400,name:"All",index:7},{percentage:Math.round(percentage),count:count,name:"fff",index:8},{percentage:Math.round(percentage),count:count,name:"ccc",index:3}];


function sortItems(a, b) {
  if (a.name === 'All') {
    return -1
  }

  if (b.name === 'All') {
    return 1;
  }

  if (a.name === selectedName) {
    return -1
  }

  if (b.name === selectedName) {
    return 1
  }

  return a.index - b.index;

}


console.log(items.sort(sortItems));

1 Comment

Have minified input data and wrapped your code in snippet.
1

You can try something like this:

Idea

  • (a.name !== priorityName) will yield a boolean value. When you use -(minus) operator on them, it is converted to numeric value(true: 1, false: 0).
  • So if both are neither of priority, both will yield 1 and output will be 0, which is falsey in JS.
  • Failure of previous expression will call current expression and would loop till last expression

var selectedName = 'fff';
var priorityName = "All";
var percentage = 50.4, count= 0;
var data=[{percentage:Math.round(percentage),count:count,name:"bbb",index:11},{percentage:Math.round(percentage),count:200,name:"aaa",index:2},{percentage:Math.round(percentage),count:400,name:"All",index:7},{percentage:Math.round(percentage),count:count,name:"fff",index:8},{percentage:Math.round(percentage),count:count,name:"ccc",index:3}];
  
data.sort(function(a,b){
  return  (a.name !== priorityName) - (b.name !== priorityName) ||
          (a.name !== selectedName) - (b.name !== selectedName) ||
           a.index - b.index;
})

console.log(data)

Comments

1

You can use a helping object holding the priority of each element. In your particular case, the highest priority has All value.

So firstly we sort the values with higher priority (All, 'fff') and when it's done, we sort the rest by the index value.

Note: Since we are sorting it by ascending order the priority values have to be negative. If we would sort it by a descending order (b - a), they would be positive.

var arr = [{percentage:Math.round("percentage"),count:"count",name:"bbb",index:11},{percentage:Math.round("percentage"),count:200,name:"aaa",index:2},{percentage:Math.round("percentage"),count:400,name:"All",index:7},{percentage:Math.round("percentage"),count:"count",name:"fff",index:8},{percentage:Math.round("percentage"),count:"count",name:"ccc",index:3}],
    selectedName = 'fff',

result = arr.sort(function(a,b){
  var order = {All: -2, [selectedName]: -1, default: 0};
  return (order[a.name] || order.default) - (order[b.name] || order.default) || a.index - b.index;
});

console.log(result);

1 Comment

Better than mine. +1 Just add some explanation

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.