Reputation: 30262
How would one sort the following object to correct alphabetical order of names?
var users_by_id = {
'12': ['Ted', 34, 'Male'],
'13': ['Ben', 36, 'Male'],
'14': ['Alice', 42, 'Female']
}
var users_by_name = {
'14': ['Alice', 42, 'Female'],
'13': ['Ben', 36, 'Male'],
'12': ['Ted', 34, 'Male']
}
I have a plan which would need two passes over the object, but I am not sure if there is a simpler way to do it. The plan I have is this (I am using jQuery):
var users_by_name = {};
var names = [];
$.each(users_by_id, function(id, props) {
names.push(props[0]);
});
names.sort();
$.each(names, function(i, n) {
$.each(users_by_id, function(id, props) {
if(n == props[0]) users_by_name[id] = props;
});
});
Upvotes: 2
Views: 1489
Reputation: 5822
Another option that makes use of Array.prototype.sort function
var users_by_id = {
'0': ['Ted', 34, 'Male'],
'1': ['Ben', 36, 'Male'],
'2': ['Alice', 42, 'Female']
}
// as long as length is bigger than max object key value
users_by_id.length = Object.keys( users_by_id ).length;
Array.prototype.sort.call( users_by_id, function( a, b ) {
var aName = a[0].toLowerCase();
var bName = b[0].toLowerCase();
if( aName > bName ) return 1;
if( aName < bName ) return -1;
return 0;
});
There are a few caveats to the above:
If you do not use contiguous numbers as keys and do the following:
var users_by_id = {
'12': ['Ted', 34, 'Male'],
'13': ['Ben', 36, 'Male'],
'14': ['Alice', 42, 'Female']
}
Once sorted the object's sorted numeric keys will be renamed => 0,1,2
Take a look at the fiddle here
Upvotes: 0
Reputation: 30262
OK, I got it. As has been pointed in the comments, Objects do not have any order. So no matter in what order the members are added (or defined), iterating over the object will produce the same result.
So, I should change my approach. A bit of background is neccessary to see why the new method would work (which is missing in the question by the way).
I have a users table and I want to display an html table with users in alphabetical order like so:
<tr id="user-N"><td>NAME</td><td>AGE</td><td>GENDER</td></tr>
And here is what I came by:
var name_ids = [];
var trows = '', thisNID;
$.each(users_by_id, function(id, props) {
name_ids.push(props[0]+':'+id);
});
name_ids.sort();
$.each(name_ids, function(i,nid) {
thisNID = nid.split(':');
trows += '<tr id="user-' + thisNID[1] + '">';
trows += '<td>' + users_by_id[thisNID[1]][0] + '</td>';
trows += '<td>' + users_by_id[thisNID[1]][1] + '</td>';
trows += '<td>' + users_by_id[thisNID[1]][2] + '</td>';
trows += '</tr>';
});
Upvotes: 0
Reputation: 3917
Sorting is usually made when you have to iterate on a collection. So... my suggestion is to ad to methods to your object's prototype - .keysById
and .keysByName
which have to return keys ordered by the condition you mentioned above. So when you have to iterate by name you can do:
var kbn = yourObj.keysByName();
for(var i=0; i<yourObj.length;i++) {
... yourObj[kbn[i]] ....
}
You can do this methods, i'm sure, so I won't give examples.
yourObj.prototype.keysByName = function() { ... }
Upvotes: 0
Reputation: 48789
If you want to keep your Object based storage instead of using an Array, you'll need to create Arrays of the properties of the Object, and sort that to get an order.
var users = {
'12': ['Ted', 34, 'Male'],
'13': ['Ben', 36, 'Male'],
'14': ['Alice', 42, 'Female']
};
var props = Object.keys(users);
var user_props_by_name = props.slice().sort(function(prop_a, prop_b) {
return users[prop_a][0].localeCompare(users[prop_b][0]);
});
var user_props_by_age = props.slice().sort(function(prop_a, prop_b) {
return users[prop_a][1] - users[prop_b][1];
});
Then you can iterate the Array and use the property names to look up items in the Object.
user_props_by_name.forEach(function(prop) {
console.log(users[prop]);
});
user_props_by_age.forEach(function(prop) {
console.log(users[prop]);
});
This will take some maintenance though when adding and removing users. You would probably want to create a layer that adds and removes users, and updates the sort Arrays at the same time.
Upvotes: 3
Reputation: 1291
sort takes an optional parameter which is a compare function https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort
var data =[
['Ted', 34, 'Male'],
['Ben', 36, 'Male'],
['Alice', 42, 'Female']
];
var sortbyid = data.sort(function(a,b){return a[1]<b[1] ? -1 : a[1]>b[1] ? 1 : 0});
var sortbyname = data.sort(function(a,b){return a[0]<b[0] ? -1 : a[0]>b[0] ? 1 : 0});
Upvotes: 0