Iterating over a JavaScript object in sort order based on particular key value of a child object

谁都会走 提交于 2019-11-30 03:38:46

问题


Short version: I'm looking for the JavaScript equivalent of Perl's

for my $key ( sort { $hash{$a}{foo} cmp $hash{$b}{foo} } keys %hash ) {
    # do something with $key
}

More detail:

I have a JSON object which consists of a bunch of other JSON objects which have identical properties to each other, like a hash of hashes in Perl: eg:

var peopleobj = { 
    "0291" : { "Forename" : "Jeremy", "Surname" : "Dyson" },
    "0398" : { "Forename" : "Billy", "Surname" : "Bunter" },
    "6714" : { "Forename" : "Harry", "Surname" : "Peterson" },
    "9080" : { "Forename" : "Barry", "Surname" : "Mainwaring"}
}

I want to iterate through the objects in peopleobj in order of the surname values, eg to print out the names in surname order. Plain JavaScript or jQuery solutions will work in the context in which this is being deployed.

Thanks in advance for your valuable time.


回答1:


Interesting question... One plain JavaScript solution is to create an index for your objects in a separate array, based on the 'Surname' property. Something like this1:

var peopleobj = { 
   "0291" : { "Forename" : "Jeremy", "Surname" : "Dyson" },
   "0398" : { "Forename" : "Billy", "Surname" : "Bunter" },
   "6714" : { "Forename" : "Harry", "Surname" : "Peterson" },
   "9080" : { "Forename" : "Barry", "Surname" : "Mainwaring" }
};

var index = [];

// build the index
for (var x in peopleobj) {
   index.push({ 'key': x, 'Surname': peopleobj[x]['Surname'] });
}

// sort the index
index.sort(function (a, b) { 
   var as = a['Surname'], 
       bs = b['Surname']; 

   return as == bs ? 0 : (as > bs ? 1 : -1); 
}); 

Now you would be able to iterate over your index array:

for (var i = 0; i < index.length; i++) {
   console.log(peopleobj[index[i]['key']]['Surname']);
}

Result (Tested in Firebug console):

Bunter
Dyson
Mainwaring
Peterson

You may want to wrap this up into some sort of reusable Iterator object, even though it would be difficult to get as terse as Perl:

// Our reusable Iterator class:
function MyIterator (o, key) {
   this.index = [];
   this.i = 0;
   this.o = o;

   for (var x in o) {
      this.index.push({ 'key': x, 'order': o[x][key] });
   }

   this.index.sort(function (a, b) { 
      var as = a['order'], 
          bs = b['order']; 

      return as == bs ? 0 : (as > bs ? 1 : -1); 
   }); 

   this.len = this.index.length;
}

MyIterator.prototype.next = function () {
   return this.i < this.len ?
          this.o[this.index[this.i++]['key']] :
          null;
};

Then use it as follows:

// Our JavaScript object:
var peopleobj = { 
   "0291" : { "Forename" : "Jeremy", "Surname" : "Dyson" },
   "0398" : { "Forename" : "Billy", "Surname" : "Bunter" },
   "6714" : { "Forename" : "Harry", "Surname" : "Peterson" },
   "9080" : { "Forename" : "Barry", "Surname" : "Mainwaring" }
};

// Build the Iterator object, using the 'Surname' field:
var surnameIter = new MyIterator(peopleobj, 'Surname');

// Iterate:
var i;

while (i = surnameIter.next()) {
   console.log(i['Surname'] + ' ' + i['Forename']);
}

Result:

Bunter Billy
Dyson Jeremy
Mainwaring Barry
Peterson Harry

1 You may want to use the hasOwnProperty() method to ensure that the properties belong to your object and are not inherited from Object.prototype:

for (var x in peopleobj) {
   if (peopleobj.hasOwnProperty(x)) {
      index.push({ 'key': x, 'Surname': peopleobj[x]['Surname'] });
   }
}


来源:https://stackoverflow.com/questions/4041762/iterating-over-a-javascript-object-in-sort-order-based-on-particular-key-value-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!