javascript - How to sort array of objects and subset of array
问题描述
Schema
var my_array = [
{
"title": "a",
"pinned": {
"status": "true",
"order": "1"
}
},
{
"title": "d",
"pinned": {
"status": "false",
"order": "n/a"
}
},
{
"title": "c",
"pinned": {
"status": "true",
"order": "0"
}
},
{
"title": "b",
"pinned": {
"status": "false",
"order": "n/a"
}
}
];
Desired Behaviour
Sort objects by title
alphabetically,
unless they have a pinned
status of true
,
in which case move this "subset" of items to the beginning of the array,
sorted by their pinned.order
value.
An example scenario would be a forum which had posts sorted by date, but also had sticky posts at the top, which were sorted by a defined order.
The original schema would, therefore, be displayed as:
[
{// i am at the top, because i have a pinned status of true and order of 0
"title": "c",
"pinned": {
"status": "true",
"order": "0"
}
},
{// i am second from the top, because i have a pinned status of true and order of 1
"title": "a",
"pinned": {
"status": "true",
"order": "1"
}
},
{// i follow in alphabetical order
"title": "b",
"pinned": {
"status": "false",
"order": "n/a"
}
},
{// i follow in alphabetical order
"title": "d",
"pinned": {
"status": "false",
"order": "n/a"
}
}
]
What I've Tried
my_array.sort(function(a, b) {
return a.pinned.order.localeCompare(b.pinned.order) || a.title.localeCompare(b.title);
});
based on this answer:
https://stackoverflow.com/a/45741804
I also tried...
I thought about creating two separate arrays based on the value of pinned.status
, sorting them separately, and then recombining them (as shown below), but I'm wondering if there is something more elegant?
var my_array = [
{
"title": "a",
"pinned": {
"status": "true",
"order": "1"
}
},
{
"title": "d",
"pinned": {
"status": "false",
"order": "n/a"
}
},
{
"title": "c",
"pinned": {
"status": "true",
"order": "0"
}
},
{
"title": "b",
"pinned": {
"status": "false",
"order": "n/a"
}
}
];
var my_subset = [];
for (var i = 0; i < my_array.length; i++) {
if (my_array[i].pinned.status === "true") {
// add to subset
my_subset.push(my_array[i]);
// remove from original array
my_array.splice(i, 1);
}
}
// sort "pruned" original array alphabetically
my_array.sort(function(a, b) {
return a.title.localeCompare(b.title);
});
// sort subset array by pinned.order
my_subset.sort(function(a, b) {
return a.pinned.order.localeCompare(b.pinned.order, undefined, { numeric: true });
});
// prepend subset to original array
var new_array = my_subset.concat(my_array);
// array is sorted as desired
console.log(new_array);
解决方案
首先通过将数字字符串设为数字并将布尔字符串设为布尔值来修复数据:
for (const item of my_array) {
item.pinned.status = JSON.parse(item.pinned.status);
item.pinned.order = Number(item.pinned.order);
}
现在您不必将它们作为字符串进行比较。否则你的方法基本上没问题,你只是忘记了一个项目是否应该放在顶部的最重要的指标:它的pinned.status
. 首先进行比较,以便任何已固定的项目出现在任何未固定的项目之前。
my_array.sort(function(a, b) {
return -(a.pinned.status - b.pinned.status) // reverse: true before false
|| (a.pinned.status // equal to b.pinned.status
? a.pinned.order - b.pinned.order
: a.title.localeCompare(b.title));
});
var my_array = [{
"title": "a",
"pinned": {
"status": true,
"order": 1
}
},
{
"title": "d",
"pinned": {
"status": false,
"order": 0
}
},
{
"title": "c",
"pinned": {
"status": true,
"order": 0
}
},
{
"title": "b",
"pinned": {
"status": false,
"order": 0
}
}
];
my_array.sort(function(a, b) {
return -(a.pinned.status - b.pinned.status) // reverse: true before false
||
(a.pinned.status // equal to b.pinned.status
?
a.pinned.order - b.pinned.order :
a.title.localeCompare(b.title));
});
console.log(my_array);
你也可以做
my_array.sort(function(a, b) {
return -(a.pinned.status - b.pinned.status) // reverse: true before false
|| a.pinned.order - b.pinned.order
|| a.title.localeCompare(b.title);
});
因为未固定的项目具有相同的顺序 ( NaN
) 但前者更明确。
推荐阅读
- c# - 释放上下文并再次创建
- java - 如何使用 415 Unknown Media Type 记录 Spring 拒绝的 Content-Type?
- bbedit - 在 .Rmd 文件上运行 BBEdit 中的 make
- powershell - TypeConverter(注册)在 PowerShell 中抛出 NullRefException
- java - 在springboot中搜索多个字段并实现分页
- java - 在火花流中提供来自 tcp socker 的数据模式 - JAVA - SPARK
- pandas - 根据条件将列从 1 df 复制到另一个
- jenkins - 执行 Parallel Jenkins 步骤并独立于第二步执行状态进入下一阶段
- excel - 当单元格区域链接到另一个工作表时,为什么计数公式会返回 0?
- excel - 以更有效的方式隐藏/显示行