使用 complex/dynamic 标准(升序和降序)对包含对象的数组进行排序?
Sorting array containing objects using complex/dynamic criteria (ascending and descending)?
我们有一个包含数据的数组,我想按 users
键对它进行排序:
如果 users
有 1 个对象,我按其 name
属性 排序。
如果 users
有超过 1 个条目,我按 users.length
排序。
示例:
DESCENDING: Zorya, Gorya, Dorya, Borya, Aorya, 4, 2, 0
ASCENDING: Aorya, Borya, Dorya, Gorya, Zorya, 2, 4, 0
这是我目前所做的:
const array = [{
name: "qw",
users: [
{ name: "Borya" },
],
}, {
name: "qw",
users: [
{ name: "Gorya" },
],
}, {
name: "qw",
users: [
{ name: "Zorya" },
]
}, {
name: "qw",
users: [
{ name: "Var" },
{ name: "Var2" },
],
}, {
name: "qw",
users: [],
}, {
name: "qw",
users: [
{ name: "Aorya" },
],
}, {
name: "qw",
users: [
{ name: "rwerwerwe" },
{ name: "tregdf" },
{ name: "gdfgdf" },
{ name: "Vayetrtertrr2" },
]
}, {
name: "qw",
users: [
{ name: "Dorya" },
],
}];
function orderCustomBy(collection, key, direction) {
const direct = direction === "desc" ? -1 : 1;
let compare = (a, b) => {
if (a === null) return -1;
if (b === null) return 1;
// Just commenting this out because there's no `intlCollator` in here:
// return intlCollator.compare(a, b);
};
if (key === "users") {
compare = (a, b) => {
// What should go in here?
// intlCollator.compare(a[0].name, b[0].name);
return 1;
};
}
return [].concat(collection).sort((a, b) => {
const result = compare(a[key], b[key]);
return result * direct;
});
}
console.log(orderCustomBy(array, 'users', 'asc')
.map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
console.log(orderCustomBy(array, 'users', 'desc')
.map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
.as-console-wrapper {
max-height: 100% !important;
}
由于这些排序标准很复杂,因此最好先将复杂的数组转换为更容易推理和排序的更简单的数组。
下面的 simplifyArray()
函数就是这样做的,生成这个未排序的数组:
[ "Borya", "Gorya", "Zorya", "2", "0", "Aorya", "4", "Dorya" ]
排序应该很简单。
function simplifyArray (arr) {
return arr.map(el => {
let length = el.users.length;
if (length === 1) { return el.users[0].name; }
else return String(length);
});
}
const array = [
{
name: "qw",
users: [
{ name: "Borya" }
]
},
{
name: "qw",
users: [
{ name: "Gorya" }
]
},
{
name: "qw",
users: [
{ name: "Zorya" }
]
},
{
name: "qw",
users: [
{ name: "Var" },
{ name: "Var2" }
]
},
{
name: "qw",
users: []
},
{
name: "qw",
users: [
{ name: "Aorya" }
]
},
{
name: "qw",
users: [
{ name: "rwerwerwe" },
{ name: "tregdf" },
{ name: "gdfgdf" },
{ name: "Vayetrtertrr2" }
]
},
{
name: "qw",
users: [
{ name: "Dorya" }
]
},
];
const simplerArray = simplifyArray(array);
console.log(simplerArray);
当 key === 'users
:
时,您基本上需要考虑 compare
函数内部的一些不同组合
两者都有一个用户,所以我们比较user[0].name
。
只有 a
有一个用户,所以 a
在 b
之前。
只有 b
有一个用户,所以 b
在 a
之前。
None只有一个用户,所以我们只比较users.length
.
它将看起来像这样:
if (a.users.length === 1 && b.users.length === 1) {
// If both have a single user, sort by users[0].name:
return a.users[0].name.localeCompare(b.users[0].name);
} else if (a.users.length === 1) {
// If only `a` has a single user, `a` goes before `b`:
return -1;
} else if (b.users.length === 1) {
// If only `b` has a single user, `b` goes before `a`:
return 1;
}
// Otherwise, sort by users.length:
return a.users.length - b.users.length;
在这里您可以看到它的实际效果:
const array = [{
name: "qw",
users: [
{ name: "Borya" },
],
}, {
name: "qw",
users: [
{ name: "Gorya" },
],
}, {
name: "qw",
users: [
{ name: "Zorya" },
]
}, {
name: "qw",
users: [
{ name: "Var" },
{ name: "Var2" },
],
}, {
name: "qw",
users: [],
}, {
name: "qw",
users: [
{ name: "Aorya" },
],
}, {
name: "qw",
users: [
{ name: "rwerwerwe" },
{ name: "tregdf" },
{ name: "gdfgdf" },
{ name: "Vayetrtertrr2" },
]
}, {
name: "qw",
users: [
{ name: "Dorya" },
],
}];
function orderCustomBy(collection, key, direction) {
const direct = direction === "desc" ? -1 : 1;
let compare;
if (key === "users") {
compare = (a, b) => {
if (a.users.length === 1 && b.users.length === 1) {
// If both have a single user, sort by users[0].name:
return a.users[0].name.localeCompare(b.users[0].name);
} else if (a.users.length === 1) {
// If only `a` has a single user, `a` goes before `b`:
return -1;
} else if (b.users.length === 1) {
// If only `b` has a single user, `b` goes before `a`:
return 1;
}
// Otherwise, sort by users.length:
return a.users.length - b.users.length;
};
} else {
compare = (a, b) => {
if (a === null) return -1;
if (b === null) return 1;
// Just commenting this out because there's no `intlCollator` in here:
// return intlCollator.compare(a, b);
};
}
return [].concat(collection).sort((a, b) => compare(a, b) * direct);
}
console.log(orderCustomBy(array, 'users', 'asc')
.map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
console.log(orderCustomBy(array, 'users', 'desc')
.map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
.as-console-wrapper {
max-height: 100% !important;
}
我们有一个包含数据的数组,我想按 users
键对它进行排序:
如果
users
有 1 个对象,我按其name
属性 排序。如果
users
有超过 1 个条目,我按users.length
排序。
示例:
DESCENDING: Zorya, Gorya, Dorya, Borya, Aorya, 4, 2, 0
ASCENDING: Aorya, Borya, Dorya, Gorya, Zorya, 2, 4, 0
这是我目前所做的:
const array = [{
name: "qw",
users: [
{ name: "Borya" },
],
}, {
name: "qw",
users: [
{ name: "Gorya" },
],
}, {
name: "qw",
users: [
{ name: "Zorya" },
]
}, {
name: "qw",
users: [
{ name: "Var" },
{ name: "Var2" },
],
}, {
name: "qw",
users: [],
}, {
name: "qw",
users: [
{ name: "Aorya" },
],
}, {
name: "qw",
users: [
{ name: "rwerwerwe" },
{ name: "tregdf" },
{ name: "gdfgdf" },
{ name: "Vayetrtertrr2" },
]
}, {
name: "qw",
users: [
{ name: "Dorya" },
],
}];
function orderCustomBy(collection, key, direction) {
const direct = direction === "desc" ? -1 : 1;
let compare = (a, b) => {
if (a === null) return -1;
if (b === null) return 1;
// Just commenting this out because there's no `intlCollator` in here:
// return intlCollator.compare(a, b);
};
if (key === "users") {
compare = (a, b) => {
// What should go in here?
// intlCollator.compare(a[0].name, b[0].name);
return 1;
};
}
return [].concat(collection).sort((a, b) => {
const result = compare(a[key], b[key]);
return result * direct;
});
}
console.log(orderCustomBy(array, 'users', 'asc')
.map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
console.log(orderCustomBy(array, 'users', 'desc')
.map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
.as-console-wrapper {
max-height: 100% !important;
}
由于这些排序标准很复杂,因此最好先将复杂的数组转换为更容易推理和排序的更简单的数组。
下面的 simplifyArray()
函数就是这样做的,生成这个未排序的数组:
[ "Borya", "Gorya", "Zorya", "2", "0", "Aorya", "4", "Dorya" ]
排序应该很简单。
function simplifyArray (arr) {
return arr.map(el => {
let length = el.users.length;
if (length === 1) { return el.users[0].name; }
else return String(length);
});
}
const array = [
{
name: "qw",
users: [
{ name: "Borya" }
]
},
{
name: "qw",
users: [
{ name: "Gorya" }
]
},
{
name: "qw",
users: [
{ name: "Zorya" }
]
},
{
name: "qw",
users: [
{ name: "Var" },
{ name: "Var2" }
]
},
{
name: "qw",
users: []
},
{
name: "qw",
users: [
{ name: "Aorya" }
]
},
{
name: "qw",
users: [
{ name: "rwerwerwe" },
{ name: "tregdf" },
{ name: "gdfgdf" },
{ name: "Vayetrtertrr2" }
]
},
{
name: "qw",
users: [
{ name: "Dorya" }
]
},
];
const simplerArray = simplifyArray(array);
console.log(simplerArray);
当 key === 'users
:
compare
函数内部的一些不同组合
两者都有一个用户,所以我们比较
user[0].name
。只有
a
有一个用户,所以a
在b
之前。只有
b
有一个用户,所以b
在a
之前。None只有一个用户,所以我们只比较
users.length
.
它将看起来像这样:
if (a.users.length === 1 && b.users.length === 1) {
// If both have a single user, sort by users[0].name:
return a.users[0].name.localeCompare(b.users[0].name);
} else if (a.users.length === 1) {
// If only `a` has a single user, `a` goes before `b`:
return -1;
} else if (b.users.length === 1) {
// If only `b` has a single user, `b` goes before `a`:
return 1;
}
// Otherwise, sort by users.length:
return a.users.length - b.users.length;
在这里您可以看到它的实际效果:
const array = [{
name: "qw",
users: [
{ name: "Borya" },
],
}, {
name: "qw",
users: [
{ name: "Gorya" },
],
}, {
name: "qw",
users: [
{ name: "Zorya" },
]
}, {
name: "qw",
users: [
{ name: "Var" },
{ name: "Var2" },
],
}, {
name: "qw",
users: [],
}, {
name: "qw",
users: [
{ name: "Aorya" },
],
}, {
name: "qw",
users: [
{ name: "rwerwerwe" },
{ name: "tregdf" },
{ name: "gdfgdf" },
{ name: "Vayetrtertrr2" },
]
}, {
name: "qw",
users: [
{ name: "Dorya" },
],
}];
function orderCustomBy(collection, key, direction) {
const direct = direction === "desc" ? -1 : 1;
let compare;
if (key === "users") {
compare = (a, b) => {
if (a.users.length === 1 && b.users.length === 1) {
// If both have a single user, sort by users[0].name:
return a.users[0].name.localeCompare(b.users[0].name);
} else if (a.users.length === 1) {
// If only `a` has a single user, `a` goes before `b`:
return -1;
} else if (b.users.length === 1) {
// If only `b` has a single user, `b` goes before `a`:
return 1;
}
// Otherwise, sort by users.length:
return a.users.length - b.users.length;
};
} else {
compare = (a, b) => {
if (a === null) return -1;
if (b === null) return 1;
// Just commenting this out because there's no `intlCollator` in here:
// return intlCollator.compare(a, b);
};
}
return [].concat(collection).sort((a, b) => compare(a, b) * direct);
}
console.log(orderCustomBy(array, 'users', 'asc')
.map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
console.log(orderCustomBy(array, 'users', 'desc')
.map(item => item.users.length === 1 ? item.users[0].name : item.users.length));
.as-console-wrapper {
max-height: 100% !important;
}