2

如何对以下对象进行排序以更正名称的字母顺序?

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']
}

我有一个计划,需要两次通过对象,但我不确定是否有更简单的方法来做到这一点。我的计划是这样的(我正在使用 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;
  });
});
4

5 回答 5

3

如果要保留基于对象的存储而不是使用数组,则需要创建对象属性的数组,然后对其进行排序以获得订单。

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];
});

然后您可以迭代数组并使用属性名称来查找对象中的项目。

user_props_by_name.forEach(function(prop) {
    console.log(users[prop]);
});

user_props_by_age.forEach(function(prop) {
    console.log(users[prop]);
});

但是,在添加和删除用户时,这将需要一些维护。您可能希望创建一个添加和删除用户的层,同时更新排序数组。

于 2012-11-03T00:12:35.280 回答
0

sort 接受一个可选参数,它是一个比较函数 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});
于 2012-11-03T00:07:14.197 回答
0

好,我知道了。正如评论中所指出的,对象没有任何顺序。因此,无论添加(或定义)成员的顺序如何,迭代对象都会产生相同的结果

所以,我应该改变我的方法。需要了解一些背景知识才能了解为什么新方法会起作用(顺便说一下,问题中缺少这一点)。

我有一个用户表,我想按字母顺序显示一个包含用户的 html 表,如下所示:

<tr id="user-N"><td>NAME</td><td>AGE</td><td>GENDER</td></tr>

这就是我的来历:

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>';
});
于 2012-11-03T00:51:47.547 回答
0

另一个使用 Array.prototype.sort 函数的选项

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;
});

上面有一些警告:

  1. 对象必须包含长度属性
  2. length 属性的值必须大于对象键的最大值

如果您不使用连续数字作为键并执行以下操作:

   var users_by_id = {
           '12': ['Ted', 34, 'Male'],
           '13': ['Ben', 36, 'Male'],
           '14': ['Alice', 42, 'Female']
     }

排序后,对象的排序数字键将被重命名 => 0,1,2

看看这里的小提琴

于 2012-11-03T02:34:52.643 回答
0

当您必须对集合进行迭代时,通常会进行排序。所以...我的建议是添加到对象原型的方法 -.keysById并且.keysByName必须返回按您上面提到的条件排序的键。因此,当您必须按名称迭代时,您可以执行以下操作:

var kbn = yourObj.keysByName(); 
for(var i=0; i<yourObj.length;i++) { 
  ... yourObj[kbn[i]] ....  
}

你可以使用这种方法,我敢肯定,所以我不会举例。

yourObj.prototype.keysByName = function() { ... }
于 2012-11-03T00:28:58.860 回答