按子属性排序javascript对象数组(可能缺少)

时间:2015-03-15 08:10:59

标签: javascript arrays sorting

我有一个大型数据集(存储在数组中的400 - 4,000个对象),我试图通过用户选择的字段过滤它们。

现在我正在使用此功能,在另一个SO问题上找到:

var sort = function (prop, arr) {
    prop = prop.split('.');
    var len = prop.length;

    arr.sort(function (a, b) {
        var i = 0;
        while( i < len ) {
            a = a[prop[i]];
            b = b[prop[i]];
            i++;
        }
        if (a < b) {
            return -1;
        } else if (a > b) {
            return 1;
        } else {
            return 0;
        }
    });
    return arr;
};

示例数据 - 我想按friends计数对对象进行排序:

var data = [
    {
        name: 'Jim',
        friends: {
            count: 20,
            url: 'http://foo.com'
        }
    },{
        name: 'Lucy',
    },{
        name: 'Phil',
        friends: {
            count: 450,
            url: 'http://moo.com'
        }
    }
];

注意&#34;露西&#34;没有friends对象 - 所以当我运行sort('friends.count', data);时,脚本会中断。

理想情况下,我喜欢那些没有我排序的属性放在数组末尾的对象。关于如何实现这一点的任何想法?

2 个答案:

答案 0 :(得分:3)

例如,

&#13;
&#13;
var data = [
    {
        name: 'Jim',
        friends: {
            count: 20,
            url: 'http://foo.com'
        }
    },{
        name: 'Lucy',
    },{
        name: 'Phil',
        friends: {
            count: 450,
            url: 'http://moo.com'
        }
    }
];

safeGet = function(obj, prop, defaultValue) {
  try {
    return obj[prop]
  } catch(e) {
    return defaultValue
  }
}


data.sort(function(x, y) {
  return (
    safeGet(x.friends, 'count', Infinity) - 
    safeGet(y.friends, 'count', Infinity));
});

document.write("<pre>" + JSON.stringify(data,0,3));
&#13;
&#13;
&#13;

如果整个属性链(friends.count)是动态的,请更改safeGet,以便迭代道具列表:

&#13;
&#13;
var data = [
    {
        name: 'Jim',
        friends: {
            count: 20,
            url: 'http://foo.com'
        }
    },{
        name: 'Lucy',
    },{
        name: 'Phil',
        friends: {
            count: 450,
            url: 'http://moo.com'
        }
    }
];

safeGet = function(obj, props, defaultValue) {
  try {
    return props.split('.').reduce(function(obj, p) {
      return obj[p];
    }, obj);
  } catch(e) {
    return defaultValue
  }
}


data.sort(function(x, y) {
  return (
    safeGet(x, 'friends.count', Infinity) - 
    safeGet(y, 'friends.count', Infinity));
});

document.write("<pre>" + JSON.stringify(data,0,3));
&#13;
&#13;
&#13;

如果您希望没有朋友的人先行,而不是最后,请将Infinity更改为-Infinity

答案 1 :(得分:0)

您的功能可以修改以检查是否存在属性:

var sort = function (prop, arr) {
    prop = prop.split('.');
    var len = prop.length;

    arr.sort(function (a, b) {
        var i = 0;
        var key;

        while( i < len ) {
            key = prop[i];

            if(!a.hasOwnProperty(key)) return 1;
            if(!b.hasOwnProperty(key)) return -1;

            a = a[key];
            b = b[key];
            i++;
        }
        if (a < b) {
            return -1;
        } else if (a > b) {
            return 1;
        } else {
            return 0;
        }
    });
    return arr;
};

这样它就会起作用。我为这个例子做了一个jsbin

@ georg的答案不适用于动态选择的属性。