在javascript

时间:2018-07-31 14:37:45

标签: javascript arrays sorting javascript-objects

我想按“用户”对象内的“名称”对以下数组进行排序

 var myArr = [
 {"id":1,"user":{"name":"allen","id":101}},
 {"id":2,"user":{"name":"martin","id":102}}
]

我该怎么做?

我有一种方法可以对对象数组进行排序,但是我不能将其用于对象数组

这是方法:

function dynamicSort(property) {
    var sortOrder = 1;
    if (property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a, b) {
            var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

然后我可以使用此排序:

myArr.sort(dynamicSort("id"));

6 个答案:

答案 0 :(得分:5)

我会将属性创建为getter函数(对于复杂的示例。您可以检查propFn是否为函数,请在下面将其用于更复杂的函数。请参见this answer,以检查propFn是否为函数)。

var myArr = [
  {"id":1,"user":{"name":"allen","id":101}},
  {"id":2,"user":{"name":"martin","id":102}}
]

function dynamicSort(propFn, sortOrder = 1) {
    return function (a, b) {
        var result = (propFn(a) < propFn(b)) ? -1 : (propFn(a) > propFn(b)) ? 1 : 0;
        return result * sortOrder;
    }
}

console.log(myArr.sort(dynamicSort((obj) => obj.user.name)));
console.log(myArr.sort(dynamicSort((obj) => obj.user.name, -1)));

或者,您可以看看:Convert JavaScript string in dot notation into an object reference

这将使您了解如何将句点表示法转换为嵌套对象,但是我建议阅读顶部的免责声明。

要保持向后兼容性,您可以在下面使用以下内容:

var myArr = [
  {"id":1,"user":{"name":"allen","id":101}},
  {"id":2,"user":{"name":"martin","id":102}}
]

function dynamicSort(propFn, sortOrder = 1) {
    if (typeof propFn === "string") {
        let prop = propFn;
        if (prop[0] === "-") {
            sortOrder = -1;
            prop = prop.substr(1);
        }

        propFn = (obj) => obj[prop];
    }
    return function (a, b) {
        var result = (propFn(a) < propFn(b)) ? -1 : (propFn(a) > propFn(b)) ? 1 : 0;
        return result * sortOrder;
    }
}

console.log(myArr.sort(dynamicSort((obj) => obj.user.name)));
console.log(myArr.sort(dynamicSort((obj) => obj.user.name, -1)));
console.log(myArr.sort(dynamicSort("id")));
console.log(myArr.sort(dynamicSort("-id")));

答案 1 :(得分:2)

编辑:

如果由于键名中的句点而遇到问题,则此方法可能更适合作为解决方案。路径只必须以方括号符号访问器或以点开头:

select t.*, gs.date1
from t cross join lateral
     generate_series(t.created_at, t.last_date, interval '1 day') gs(date1)


使用this answer中的function dynamicSort(property, order) { order||(order=1); const getter = new Function("obj", "return obj" + property + ";"); return function(a, b) { var result = (getter(a) < getter(b)) ? -1 : (getter(a) > getter(b)) ? 1 : 0; return result * order; } } var myArr = [{ "id": 1, "user": { "name": "allen", "id": 101 } }, { "id": 2, "user": { "name": "martin", "id": 102 } }, { "id": 3, "user": { "name": "barry", "id": 103 } } ] console.log(JSON.stringify(myArr.sort(dynamicSort(".user.name"))));方法,您可以重写函数以获取要作为排序依据的属性的路径:

Object.byString()

如果您将订单作为第二个参数,我认为使用起来会更清晰,更容易,这意味着您的函数应该或多或少像这样:

var myArr = [
 {"id":1,"user":{"name":"allen","id":101}},
 {"id":2,"user":{"name":"martin","id":102}},
 {"id":3,"user":{"name":"barry","id":103}}
]

console.log(JSON.stringify(myArr.sort(dynamicSort("user.name"))));


function dynamicSort(property) {
    var sortOrder = 1;
    if (property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a, b) {
            var result = (byString(a, property) < byString(b, property)) ? -1 : (byString(a, property) > byString(b, property)) ? 1 : 0;
        return result * sortOrder;
    }
}

function byString(o, s) {
    s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
    s = s.replace(/^\./, '');           // strip a leading dot
    var a = s.split('.');
    for (var i = 0, n = a.length; i < n; ++i) {
        var k = a[i];
        if (k in o) {
            o = o[k];
        } else {
            return;
        }
    }
    return o;
}

答案 2 :(得分:0)

您可以使用sort方法,但是首先需要获取嵌套属性,为此您可以传递字符串,然后使用reduce方法获取属性。

 var myArr = [{"id":2,"user":{"name":"martin","id":102}}, {"id":1,"user":{"name":"allen","id":101}}]

function dynamicSort(arr, prop) {
  function getVal(obj, prop) {
    return prop.split('.').reduce((r, e) => r[e] || {}, obj)
  }

  arr.sort((a, b) => {
    let vA = getVal(a, prop);
    let vB = getVal(b, prop);
    return vA.localeCompare(vB)
  })
}

dynamicSort(myArr, "user.name")
console.log(myArr)

答案 3 :(得分:0)

请查看this SO answer,以找到基本相似的问题的答案。

由于该答案中的函数与您调用的函数不同,将要排序的数组作为参数传入,因此您可以将其重构为与现有dynamicSort函数相同的方式,如下所示:

function dynamicSort(property) {
    var sortOrder = 1;
    if (property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    var prop = property.split('.');
    var len = prop.length;

    return function (a, b) {
        var i = 0;
        while( i < len ) { a = a[prop[i]]; b = b[prop[i]]; i++; }
        var result = (a < b) ? -1 : (a > b) ? 1 : 0;
        return result * sortOrder;
    }
}

然后可以这样称呼它:myArr.sort(this.dynamicSort("user.name"))

以下是一个有效的代码段,用于演示:

function dynamicSort(property) {
    var sortOrder = 1;
    if (property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
	var prop = property.split('.');
    var len = prop.length;

    return function (a, b) {
		var i = 0;
        while( i < len ) { a = a[prop[i]]; b = b[prop[i]]; i++; }
        var result = (a < b) ? -1 : (a > b) ? 1 : 0;
        return result * sortOrder;
    }
}

var myArr = [
	{"id":1,"user":{"name":"allen","id":101}},
	{"id":2,"user":{"name":"martin","id":102}},
	{"id":3,"user":{"name":"beth","id":103}},
];

console.log(myArr.sort(this.dynamicSort("user.name"))); //expected output: [{id:1, user:{name:"allen",...}}, {id:3, user:{name:"beth",...}}, {id:2, user:{name:"martin",...}}]

答案 4 :(得分:-1)

尝试一下。对我来说很好

var sortedArray = myArr.sort((a, b) => {

        const
            nameA = a.user.name.toUpperCase(),
            nameB = b.user.name.toUpperCase();

        if(nameA < nameB)
            return -1;

        if(nameA > nameB)
            return 1;

        return 0;
    });

答案 5 :(得分:-1)

myArr.sort(function(a, b) {
    return a.user.name.localeCompare(b.user.name);
});