基于子对象的特定键值以排序顺序迭代JavaScript对象

Jon*_*nah 9 javascript sorting iteration json hashtable

简短版本:我正在寻找与Perl相当的JavaScript

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

更多详情:

我有一个JSON对象,它由一堆其他JSON对象组成,这些对象具有相同的属性,就像Perl中哈希的哈希:例如:

var peopleobj = { 
    "0291" : { "Forename" : "Jeremy", "Surname" : "Dyson" },
    "0398" : { "Forename" : "Billy", "Surname" : "Bunter" },
    "6714" : { "Forename" : "Harry", "Surname" : "Peterson" },
    "9080" : { "Forename" : "Barry", "Surname" : "Mainwaring"}
}
Run Code Online (Sandbox Code Playgroud)

我想peopleobj按照姓氏值的顺序迭代对象,例如以姓氏顺序打印出姓名.简单的JavaScript或jQuery解决方案将在部署它的上下文中工作.

提前感谢您宝贵的时间.

Dan*_*llo 9

有趣的问题......一个简单的JavaScript解决方案是根据'Surname'属性在单独的数组中为对象创建索引.这样的东西1:

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); 
}); 
Run Code Online (Sandbox Code Playgroud)

现在您可以迭代您的index数组:

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

结果(在Firebug控制台中测试):

Bunter
Dyson
Mainwaring
Peterson
Run Code Online (Sandbox Code Playgroud)

您可能希望将其包装到某种可重用的Iterator对象中,即使它很难像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;
};
Run Code Online (Sandbox Code Playgroud)

然后使用如下:

// 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']);
}
Run Code Online (Sandbox Code Playgroud)

结果:

Bunter Billy
Dyson Jeremy
Mainwaring Barry
Peterson Harry
Run Code Online (Sandbox Code Playgroud)

1您可能希望使用该hasOwnProperty()方法来确保属性属于您的对象,并且不是从Object.prototype以下内容继承的:

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

  • +1.很好的答案,虽然传递给`sort()`的比较函数应该返回一个数字,而不是一个布尔值.我建议像`function(a,b){var as = a.Surname.,bs = b.Surname; 返回== bs?0 :( as> bs?1:-1); }` (2认同)