Javascript Sort by object Value that has multiple values ​​(group) only using Comparartor

I have some data formatted like this:

var data = [
        { id: 1, name:  "Netherlands", population: 17},
        { id: 1.1, name: "Rotterdam", population: 4},
        { id: 1.2, name: "Amsterdam", population: 2},
        { id: 2, name:  "USA", population: 350},
        { id: 3, name: "Germany", population: 55},
        { id: 3.1, name: "Berlin", population: 4},
        { id: 3.2, name: "Stuttgard", population: 3},
        { id: 3.3, name: "Cologne", population: 3},
        { id: 4, name: "UK", population: 60},
        { id: 5, name: "Canada", population: 30},
        { id: 5.1, name: "Ottawa", population: 2},
    ];

Basically, the name can be either a city or a country. Countries are designated as integers, and their cities as .1. Each country can have 0-3 cities.

Is it possible to write a comparator function for Array.prototype.sort, where it sorts, for example, countries in alphabetical order, and then by their cities, but preserves the integrity of the country / city group and does not mutate the data array in advance? Is it possible? If not, why? If this is not possible, it would still be interesting for me to know how to do this, sorting through the array first, although for this I would need a lot more bounce, and this is not ideal.

, :

var data = [
    { id: 5, name: "Canada", population: 30},
    { id: 5.1, name: "Ottawa", population: 2},
    { id: 3, name: "Germany", population: 55},
    { id: 3.1, name: "Berlin", population: 4},
    { id: 3.3, name: "Cologne", population: 3},
    { id: 3.2, name: "Stuttgard", population: 3},
    { id: 1, name:  "Netherlands", population: 17},
    { id: 1.2, name: "Amsterdam", population: 2},
    { id: 1.1, name: "Rotterdam", population: 4},
    { id: 4, name: "UK", population: 60},
    { id: 2, name:  "USA", population: 350},
];

, :

http://plnkr.co/edit/vPTaoh

, / array.prototype.sort , , , . .

0
4

, / Array.prototype.sort ,

, , . .

Array.prototype.sort, , , , , / ?

, (). , , , : .
( id, ).

, :

var data = [
    {id: 1, name:  "Netherlands", population: 17, cities: [
        {id: 1.1, name: "Rotterdam", population: 4},
        {id: 1.2, name: "Amsterdam", population: 2}
    ]},
    {id: 2, name: "USA", population: 350, cities: []},
    {id: 3, name: "Germany", population: 55, cities: [
        {id: 3.1, name: "Berlin", population: 4},
        {id: 3.2, name: "Stuttgard", population: 3},
        {id: 3.3, name: "Cologne", population: 3}
    ]},
    {id: 4, name: "UK", population: 60, cities: []},
    {id: 5, name: "Canada", population: 30, cities: [
        {id: 5.1, name: "Ottawa", population: 2}
    ]}
];

, .

+2

Array.prototype.sort , , , . 3.1 1.2, .

function compare(a, b) {
  const countryAName = array.find(elt => elt.id === countryA).name;
  const countryBName = array.find(elt => elt.id === countryB).name;

  return countryAName < countryBName ? -1 :
    countryAName > countryBName ? +1 :
    a.name < b.name ? -1 :
    a.name > b.name ? +1 : 0;
}

, array.find . , :

array.forEach(elt => elt.country = array.find(e => e.id === Math.floor(elt.id)).name);

:

function compare(a, b) {
  return a.country < b.country ? -1 :
    a.country > b.country ? +1 :
    a.name < b.name ? -1 :
    a.name > b.name ? +1 : 0;
}

"" , country , :

const map = [];
array.forEach(elt => { if (!(elt.id % 1)) map[Math.floor(elt.id)] = elt.name; });

function compare(a, b) {
  const countryAName = map[Math.floor(a.id)];
  const countryBName = map[Math.floor(b.id)];

 return countryAName < countryBName ? -1 :
    countryAName > countryBName ? +1 :
    a.name < b.name ? -1 :
    a.name > b.name ? +1 : 0;

} 
+1

- .

var data = [{ id: 1, name: "Netherlands", population: 17 }, { id: 1.1, name: "Rotterdam", population: 4 }, { id: 1.2, name: "Amsterdam", population: 2 }, { id: 2, name: "USA", population: 350 }, { id: 3, name: "Germany", population: 55 }, { id: 3.1, name: "Berlin", population: 4 }, { id: 3.2, name: "Stuttgart", population: 3 }, { id: 3.3, name: "Cologne", population: 3 }, { id: 4, name: "UK", population: 60 }, { id: 5, name: "Canada", population: 30 }, { id: 5.1, name: "Ottawa", population: 2 }, ],
    hash = {};

data.forEach(function (a) {
    if (a.id === Math.floor(a.id)) {
        hash[a.id] = a.name;
    }
});

data.sort(function (a, b) {
    function getHash(o) { return hash[Math.floor(o.id)]; }

    return (
        getHash(a).localeCompare(getHash(b)) ||                      // compare country
        (Math.floor(a.id) !== a.id) - (Math.floor(b.id) !== b.id) || // move int to top
        a.name.localeCompare(b.name)                                 // compare city
    );
});

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

- FF, Chrome ( WebKit, Opera) , . , , . , - , Chrome?

var data = [
        { id: 1, name:  "Netherlands", population: 17},
        { id: 1.1, name: "Rotterdam", population: 4},
        { id: 1.2, name: "Amsterdam", population: 2},
        { id: 2, name:  "USA", population: 350},
        { id: 3, name: "Germany", population: 55},
        { id: 3.1, name: "Berlin", population: 4},
        { id: 3.2, name: "Stuttgard", population: 3},
        { id: 3.3, name: "Cologne", population: 3},
        { id: 4, name: "UK", population: 60},
        { id: 5, name: "Canada", population: 30},
        { id: 5.1, name: "Ottawa", population: 2},
    ],
  sorted = data.sort((a,b) => a.id%1 === 0 && b.id%1 === 0 ? a.name.localeCompare(b.name)
                                                           : ~~a.id === ~~b.id ? a.id - b.id
                                                                               : data.find(o => o.id === ~~a.id).name.localeCompare(data.find(o => o.id === ~~b.id).name));
console.log(sorted);
Hide result

. @Bergi, try catch @Chrome . , catch, . Chrome.

var data = [
        { id: 1, name:  "Netherlands", population: 17},
        { id: 1.1, name: "Rotterdam", population: 4},
        { id: 1.2, name: "Amsterdam", population: 2},
        { id: 2, name:  "USA", population: 350},
        { id: 3, name: "Germany", population: 55},
        { id: 3.1, name: "Berlin", population: 4},
        { id: 3.2, name: "Stuttgard", population: 3},
        { id: 3.3, name: "Cologne", population: 3},
        { id: 4, name: "UK", population: 60},
        { id: 5, name: "Canada", population: 30},
        { id: 5.1, name: "Ottawa", population: 2},
    ],
  sorted = data.sort(function(a,b){
                       try {
                             return a.id%1 === 0 && b.id%1 === 0 ? a.name.localeCompare(b.name)
                                                                 : ~~a.id === ~~b.id ? a.id - b.id
                                                                                     : data.find(o => o.id === ~~a.id).name.localeCompare(data.find(o => o.id === ~~b.id).name);
                       }
                       catch(e) {console.log(JSON.stringify(data)) }
                     });
console.log(sorted);
Hide result
0

Source: https://habr.com/ru/post/1656109/


All Articles