1

I have an array that contains objects, each object has these properties:

{ country: 'United States' },
{ country: 'Netherlands' },
{ country: 'Spain' },
{ country: 'Spain' },

I want to sort the array so that the first values will be the ones with 'Spain' then show all the others. I tried with array.sort but it seems not to work. Not sure what I am doing wrong.

So far I tried with this

arr.sort(function(a, b) {return a.country === 'Spain'})

also

arr.sort(function(a, b) {if (a.country === 'Spain') {return 1}})
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
Kaiser Soze
  • 1,362
  • 3
  • 14
  • 31
  • 1
    please add what you have tried. should the rest sorted in order of occurence? – Nina Scholz Dec 17 '17 at 18:22
  • arr.sort(function(a, b) {return a.country === 'Spain'}) – Kaiser Soze Dec 17 '17 at 18:24
  • I added the code I have tried. All the answer I find are sorting the array comparing 2 values of the array, but in my case 'Spain' is a value that is outside of the array, and I need to order it based on object.country === 'Spain' – Kaiser Soze Dec 17 '17 at 18:27

3 Answers3

3

You could take a check with the string, you want to sort to top and take the delta of the comparison.

The sort order of the other countries is not stable.

var array = [{ country: 'United States' }, { country: 'Netherlands' }, { country: 'Spain' }, { country: 'Spain' }];

array.sort(function (a, b) {
    return (b.country === 'Spain') - (a.country === 'Spain');
});

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

For a stable sort, with sorting 'Spain' to top and the rest by it's original index, you could use sorting with map.

var array = [{ country: 'United States' }, { country: 'Netherlands' }, { country: 'Spain' }, { country: 'Spain' }],
    sorted = array
        .map(function (o, i) {
            return { top: o.country === 'Spain', index: i };
        })
        .sort(function (a, b) {
            return b.top - a.top || a.index - b.index;
        })
        .map(function (o) {
            return array[o.index];
        });

console.log(sorted);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • I think it should be `b - a` in order to be alphabetical? – Derek Brown Dec 17 '17 at 18:37
  • @DerekBrown, you can not subtract nonnumerical strings. – Nina Scholz Dec 17 '17 at 18:38
  • I don't mean subtracting non-numerical strings, I mean you should reverse the order of your terms in the compare function. – Derek Brown Dec 17 '17 at 18:43
  • I think this is the correct answer as it worked perfect. What if I want to order first by country and another value, for example actual country, then only by country? e.g {country: 'Spain', actualCountry: 'Netherlands'} let's say I want to order first the one who have country === 'Spain' and actualCountry === 'Netherlands' after those I want to add all the ones who have only country === 'Spain', then all the rest. :) @NinaScholz – Kaiser Soze Dec 17 '17 at 18:51
1

No actual sorting is needed. Just break it up into two different arrays, and then combine them.

This also guarantees that the original sub-ordering is maintained.

var data = [{"country":"United States"},{"country":"Netherlands"},{"country":"Spain"},{"country":"Spain"}];

var res = [].concat(...data.reduce((res, obj) =>
  (res[obj.country === "Spain" ? 0 : 1].push(obj), res)
, [[],[]]));

console.log(res);

And if you need to mutate the original, then do this:

var data = [{"country":"United States"},{"country":"Netherlands"},{"country":"Spain"},{"country":"Spain"}];

var res = Object.assign(data, [].concat(...data.reduce((res, obj) =>
  (res[obj.country === "Spain" ? 0 : 1].push(obj), res)
, [[],[]])));

console.log(data);
1

This should be fairly easy to do using Javascript array functions, particularly sort(), filter(), and reverse().

var json = [
  {
    country: 'United States'
  },
  {
    country: 'Netherlands'
  },
  {
    country: 'Spain'
  },
  {
    country: 'Spain'
  }
];

var sorted = 
  // Spain Terms First
  json.filter(j => j.country === 'Spain')
  // Add Alphabetically-Sorted Other Terms
  .concat(json.filter(j => j.country !== 'Spain').sort().reverse()); 
  
console.log(sorted);
Derek Brown
  • 4,232
  • 4
  • 27
  • 44