RedCollarPanda
RedCollarPanda

Reputation: 1481

Complex sorting

I have many structures like:

student :
 name: SomeName
 city : someSity   
 school : someschool
 date : somedate

What I want is to sort them in a way like (with test data):

Sorted_map:
    city : NY
       school: School1
             name:Name1
             name: Name2
             name: Name4
       shool: School2
             name:Name11
             name: Name21
             name: Name41

    city: WDC  
        school: School3
           name: Name22  
           name: Name29 

What I did is sorting by city :

function groupBy( array , f ) {
    var groups = {};
    array.forEach( function( o )
    {
        var group = JSON.stringify( f(o) );
        groups[group] = groups[group] || [];
        groups[group].push( o );
    });
     return groups;    
}


var result = groupBy(sudentsItems, function(item)
    {

        return unifyCity(item.city);
    }

so now it is sorted only by the "city" key. How do I sort data inside city?

I guess I need something like Map < city_key, Map < school_key, name > >;

Data sample :

[{
    "name":   "John Some",
    "city":   "NY",
    "school": "NY Central",
    "date":   1460986261733
}, {
    "name":   "Sarah Mil",
    "city":   "Moscow",
    "school": "Moscow Central",
    "date":   1460986201733
}, {
    "name":   "John Again",
    "city":   "NY",
    "school": "NY Central",
    "date":   1460986261733
}, {
    "name":   "Kit Parcer",
    "city":   "NY",
    "school": "NY Central",
    "date":   1460086261733
},  {
    "name":   "Anna Love",
    "city":   "SPB",
    "school": "SPB Central",
    "date":   1460983261733
}]

Upvotes: 1

Views: 422

Answers (2)

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48610

You can use a for-loop to iterate over all the fields in the sorters array. If, at any point, the result of the comparison is not 0 (equal) then immediately return the value.

function sortMulti(data, sorters) {
  return data.sort(function(a, b) {
    for (var i = 0; i < sorters.length; i++) {
      var result = 0;
      var f1 = a[sorters[i].field];
      var f2 = b[sorters[i].field];
      if (typeof f1 === 'string' || typeof f2 === 'string') {
        result = f1.localeCompare(f2);
      } else {
        result = f1 < f2 ? -1 : f1 > f2 ? 1 : 0;
      }
      if (sorters[i].direction === 'desc') {
        result = result * -1;
      }
      if (result !== 0) {
        return result;
      }
    }
  });
}

var data = [
  { "name": "John Some",  "city": "NY",     "school": "NY Central",     "date": 1460986261733 },
  { "name": "Sarah Mil",  "city": "Moscow", "school": "Moscow Central", "date": 1460986201733 },
  { "name": "John Again", "city": "NY",     "school": "NY Central",     "date": 1460986261733 },
  { "name": "Kit Parcer", "city": "NY",     "school": "NY Central",     "date": 1460086261733 },
  { "name": "Anna Love",  "city": "SPB",    "school": "SPB Central",    "date": 1460983261733 }
];

var sorters = [
  { field: 'city',   direction: 'asc' },
  { field: 'school', direction: 'asc' },
  { field: 'name',   direction: 'asc' }
];

document.body.innerHTML = '<pre>' + JSON.stringify(sortMulti(data, sorters), null, 4) + '</pre>';

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386578

It looks like that you are looking either for sorted or a grouped data.

var data = [{ "name": "John Some", "city": "NY", "school": "NY Central", "date": 1460986261733 }, { "name": "Sarah Mil", "city": "Moscow", "school": "Moscow Central", "date": 1460986201733 }, { "name": "John Again", "city": "NY", "school": "NY Central", "date": 1460986261733 }, { "name": "Kit Parcer", "city": "NY", "school": "NY Central", "date": 1460086261733 }, { "name": "Anna Love", "city": "SPB", "school": "SPB Central", "date": 1460983261733 }],
    object = {};

data.sort(function (a,b) {
    return a.city.localeCompare(b.city) || 
        a.school.localeCompare(b.school) || 
        a.name.localeCompare(b.name);
});

data.forEach(function (a) {
    object[a.city] = object[a.city] || {};
    object[a.city][a.school] = object[a.city][a.school] || [];
    object[a.city][a.school].push(a.name);
});

document.write('<pre>data sorted: ' + JSON.stringify(data, 0, 4) + '</pre>');
document.write('<pre>data grouped: ' + JSON.stringify(object, 0, 4) + '</pre>');

Upvotes: 2

Related Questions