I want to sort the below array by the "name" that is inside "user" object
我想通过“user”对象中的“name”对下面的数组进行排序
var myArr = [
{"id":1,"user":{"name":"allen","id":101}},
{"id":2,"user":{"name":"martin","id":102}}
]
how can I do this?
我怎样才能做到这一点?
I have a method to sort array of objects but I can't use it for array of objects of objects
我有一个方法来排序对象数组,但我不能将它用于对象的数组
this is the method:
这是方法:
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;
}
}
then I can sort using this:
然后我可以使用这个排序:
myArr.sort(dynamicSort("id"));
6 个解决方案
#1
5
I would create property as a getter function (For the complex examples. You could check if propFn is a function, use this below for the more complex ones. See this answer for checking is propFn
is a function.):
我将创建属性作为一个getter函数(对于复杂的例子。你可以检查propFn是否是一个函数,使用下面的更复杂的函数。请参阅这个答案以检查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)));
Alternatively, you can take a look at: Convert JavaScript string in dot notation into an object reference
或者,您可以查看:将点符号中的JavaScript字符串转换为对象引用
This will give you an idea of how you can convert period notation into a nested object, but I recommend reading the disclaimer at the top.
这将让您了解如何将句点符号转换为嵌套对象,但我建议您阅读顶部的免责声明。
To maintain backwards compatibility, you could use something like this below:
为了保持向后兼容性,您可以使用以下内容:
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")));
#2
2
Edit:
If you are experiencing problems because of periods in your key names, this approach may be better suited as a solution. The path just has to either start as a bracket notation accessor or with a dot:
如果由于密钥名称中存在问题而遇到问题,则此方法可能更适合作为解决方案。路径必须以括号表示法访问器或点开头:
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"))));
Using the Object.byString()
method from this answer, you can rewrite your function to take a path to the property you want to sort by:
使用此答案中的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;
}
I think it would be a little clearer and easier to use if you have the order as a second parameter, which means that your function should then more or less look like this:
如果您将订单作为第二个参数,我认为它会更清晰,更容易使用,这意味着您的函数应该或多或少看起来像这样:
function dynamicSort(property, order) {
return function(a, b) {
var result = (byString(a, property) < byString(b, property)) ? -1 : (byString(a, property) > byString(b, property)) ? 1 : 0;
return result * order;
}
}
#3
0
You could use sort
method but you first need to get nested property and for that you could pass a string and then use reduce
method to get property.
您可以使用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)
#4
0
Check out this SO answer for an answer to a fundamentally similar question.
查看此SO答案以获得对基本类似问题的答案。
Since the function in that answer is called differently than yours, with the array to be sorted passed in as a parameter, you could refactor it to be called in the same way as your existing dynamicSort
function as follows:
由于该答案中的函数与您的函数调用方式不同,要将要排序的数组作为参数传入,您可以使用与现有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;
}
}
You could then call it like so: myArr.sort(this.dynamicSort("user.name"))
.
然后你可以像这样调用它:myArr.sort(this.dynamicSort(“user.name”))。
Here is a working snippet to demonstrate:
这是一个工作片段来演示:
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",...}}]
#5
-1
Try this out. Works fine for me
试试吧。对我来说很好
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;
});
#6
-1
myArr.sort(function(a, b) {
return a.user.name.localeCompare(b.user.name);
});
#1
5
I would create property as a getter function (For the complex examples. You could check if propFn is a function, use this below for the more complex ones. See this answer for checking is propFn
is a function.):
我将创建属性作为一个getter函数(对于复杂的例子。你可以检查propFn是否是一个函数,使用下面的更复杂的函数。请参阅这个答案以检查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)));
Alternatively, you can take a look at: Convert JavaScript string in dot notation into an object reference
或者,您可以查看:将点符号中的JavaScript字符串转换为对象引用
This will give you an idea of how you can convert period notation into a nested object, but I recommend reading the disclaimer at the top.
这将让您了解如何将句点符号转换为嵌套对象,但我建议您阅读顶部的免责声明。
To maintain backwards compatibility, you could use something like this below:
为了保持向后兼容性,您可以使用以下内容:
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")));
#2
2
Edit:
If you are experiencing problems because of periods in your key names, this approach may be better suited as a solution. The path just has to either start as a bracket notation accessor or with a dot:
如果由于密钥名称中存在问题而遇到问题,则此方法可能更适合作为解决方案。路径必须以括号表示法访问器或点开头:
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"))));
Using the Object.byString()
method from this answer, you can rewrite your function to take a path to the property you want to sort by:
使用此答案中的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;
}
I think it would be a little clearer and easier to use if you have the order as a second parameter, which means that your function should then more or less look like this:
如果您将订单作为第二个参数,我认为它会更清晰,更容易使用,这意味着您的函数应该或多或少看起来像这样:
function dynamicSort(property, order) {
return function(a, b) {
var result = (byString(a, property) < byString(b, property)) ? -1 : (byString(a, property) > byString(b, property)) ? 1 : 0;
return result * order;
}
}
#3
0
You could use sort
method but you first need to get nested property and for that you could pass a string and then use reduce
method to get property.
您可以使用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)
#4
0
Check out this SO answer for an answer to a fundamentally similar question.
查看此SO答案以获得对基本类似问题的答案。
Since the function in that answer is called differently than yours, with the array to be sorted passed in as a parameter, you could refactor it to be called in the same way as your existing dynamicSort
function as follows:
由于该答案中的函数与您的函数调用方式不同,要将要排序的数组作为参数传入,您可以使用与现有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;
}
}
You could then call it like so: myArr.sort(this.dynamicSort("user.name"))
.
然后你可以像这样调用它:myArr.sort(this.dynamicSort(“user.name”))。
Here is a working snippet to demonstrate:
这是一个工作片段来演示:
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",...}}]
#5
-1
Try this out. Works fine for me
试试吧。对我来说很好
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;
});
#6
-1
myArr.sort(function(a, b) {
return a.user.name.localeCompare(b.user.name);
});