英文:
place null values at last while sorting the data
问题
I have this data which I'm displaying in the table:
[
{
"ID": 9,
"Status": "Pending",
},
{
"ID": 8,
"Status": null,
},
{
"ID": 7,
"Status": "Pending",
},
{
"ID": 10,
"Status": null,
},
{
"ID": 18,
"Status": "Completed",
},
{
"ID": 17,
"Status": "In Progress",
}
]
Sort Method:
Ascending order:
this.List.sort((a, b) => a[columnname] < b[columnname] ? 1 : a[columnname] > b[columnname] ? -1 : 0);
Descending order:
this.List.sort((a, b) => a[columnname] > b[columnname] ? 1 : a[columnname] < b[columnname] ? -1 : 0);
and using the sort function to sort the data in the table. The issue is when I sort it, I want to place null values at the end. In the current scenario, they are in between other values.
Like:
Completed
null
In Progress
null
Pending
null
...
英文:
I have this data which i'm displaying in the table
[
{
"ID": 9,
"Status": "Pending",
},
{
"ID": 8,
"Status": null,
},
{
"ID": 7,
"Status": "Pending",
},
{
"ID": 10,
"Status": null,
},
{
"ID": 18,
"Status": "Completed",
},
{
"ID": 17,
"Status": "In Progress",
}
]
Sort Method:
> Ascending order :
this.List.sort((a, b) => a[columnname] < b[columnname] ? 1 : a[columnname] > b[columnname]` ? -1 : 0);
> Descending order :
this.List.sort((a, b) => a[columnname] > b[columnname] ? 1 : a[columnname] < b[columnname] ? -1 : 0);
and using sort function to sort the data in table issue is when i sort it, i want to place null values at the last. In current scenario they are in between other values
Like
Completed
null
In Progress
null
Pending
null
..
答案1
得分: 2
这是你的排序函数的一些要点:
* 你不应该使用 `<` 和 `>` 来比较字符串。它会导致在大小写、特殊字符、数字等方面出现奇怪的结果。可以使用 `String.localeCompare` 函数来比较字符串。
* 如果你希望始终将 `null`(或其他特殊值)放在末尾,可以让它返回一个始终相同的自定义值。
这是一个示例排序函数,其中包含了对数字和字符串的检查,并始终将 null 值一起排序:
```javascript
function mySort(data, columnName, reverse) {
return data.sort((a, b) => {
const valueA = reverse ? a[columnName] : b[columnName];
const valueB = reverse ? b[columnName] : a[columnName];
if (valueA === null) {
return -1;
}
if (typeof valueA === 'string' && typeof valueB === 'string') {
return valueA.localeCompare(valueB);
}
if (typeof valueA === 'number' && typeof valueB === 'number') {
return valueA - valueB;
}
})
}
如果你调用 mySort(list, 'Status', false)
,你会注意到所有的 null 值都在末尾,而其余部分仍然被正确排序。
如果你想要在升序和降序排序中都将 null
放在末尾,你可以将特殊的 === null
检查适应成类似以下方式:
if (valueA === null) {
return reverse ? 1 : -1;
}
英文:
Couple of things for your sorting function
- You should not use
<
and>
to compare strings. It does weird things with upper/lower case, special characters, numbers, etc. there is aString.localeCompare
function that can be used to compare strings - If you want to sort
null
(or other special values) always at the end, just let it return a custom value that is always the same
This is a sample sorting function, that contains a check for number & string and always sorts null values together
function mySort(data, columnName, reverse) {
return data.sort((a, b) => {
const valueA = reverse ? a[columnName] : b[columnName];
const valueB = reverse ? b[columnName] : a[columnName];
if (valueA === null) {
return -1;
}
if (typeof valueA === 'string' && typeof valueB === 'string') {
return valueA.localeCompare(valueB);
}
if (typeof valueA === 'number' && typeof valueB === 'number') {
return valueA - valueB;
}
})
}
if you call mySort(list, 'Status', false)
you will notice that all the null values are at the end while the rest is still properly sorted.
If you want to have null
in the end for both descending and ascending you can adapt the special === null
check to something like
if (valueA === null) {
return reverse ? 1 : -1;
}
答案2
得分: 1
以下是您要翻译的内容:
const tasks = [
{ "ID": 9, "Status": "Pending" },
{ "ID": 8, "Status": null },
{ "ID": 7, "Status": "Pending" },
{ "ID": 10, "Status": null },
{ "ID": 18, "Status": "Completed" },
{ "ID": 17, "Status": "In Progress" },
];
const columnName = "Status";
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => (
(a == null) - (b == null) // move null values to the back of the array
|| -(a < b) // move `a` to the front if it's smaller than `b`
|| +(a > b) // move `a` to the back if it's greater than `b`
));
console.log(tasks);
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => {
if (a == null && b != null) return 1; // a after b
if (a != null && b == null) return -1; // a before b
if (a < b) return -1; // a before b
if (a > b) return 1; // a after b
return 0; // equal
});
const modifiers = { asc: 1, desc: -1 };
const columnName = "Status";
const direction = "desc";
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => (
(a == null) - (b == null) // move null values to the back of the array
|| modifiers[direction] * (
-(a < b) // move `a` to the front if it's smaller than `b`
|| +(a > b) // move `a` to the back if it's greater than `b`
)
));
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => {
if (a == null && b != null) return 1; // a after b
if (a != null && b == null) return -1; // a before b
if (a < b) return -1 * modifiers[direction]; // a before b
if (a > b) return 1 * modifiers[direction]; // a after b
return 0; // equal
});
英文:
A fairly short way to do this would be:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const tasks = [
{ "ID": 9, "Status": "Pending" },
{ "ID": 8, "Status": null },
{ "ID": 7, "Status": "Pending" },
{ "ID": 10, "Status": null },
{ "ID": 18, "Status": "Completed" },
{ "ID": 17, "Status": "In Progress" },
];
const columnName = "Status";
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => (
(a == null) - (b == null) // move null values to the back of the array
|| -(a < b) // move `a` to the front if it's smaller than `b`
|| +(a > b) // move `a` to the back if it's greater than `b`
));
console.log(tasks);
<!-- end snippet -->
In the snippet above we start with destructuring both comparator objects. ({ [columnName]: a }, { [columnName]: b })
stores the value of the columnName
property of the first argument in the variable a
and b
for the second argument.
We then start with (a == null) - (b == null)
to move the null
values to the back of the array. This works because true
coerces into 1
and false
coerces into 0
. So if a
is null
and b
is not, then true - false
will evaluate to 1 - 0 //=> 1
. A positive return value means that a
is placed behind b
. If we are in the opposite scenario and a
is not null
but b
is, then false - true //=> -1
. A negative return value means that a
is placed before b
.
Both 1
or -1
are truthy values, which cause the OR operator ||
to short circuit and return the first operand. If both values are null
or both values are not null
, then we end up with true - true
or false - false
which both evaluate to 0
. Since 0
is a falsy value, we'll move on to the second operand of the OR operator.
This brings us to -(a < b)
, which checks if a
is smaller than b
. When this is true -true
will evaluate into -1
, so a
is placed before b
. If this is false then -false
will evaluate into -0
, which is a falsy value and moves us to the next operand in the OR chain. Assume that a
and b
are both null
, then null < null
is false
, thus moving us on to the next OR operand. If a
and b
are both not null
, say the status string, then the strings are compared based on code point values and -1
is returned if a
is smaller than b
. Otherwise we move on to the final OR operand.
+(a > b)
is very similar to -(a < b)
, but returns 1
if a
is greater than b
. Placing a
after b
in the result.
Here are 6 example scenarios, showing the different outputs:
a = null, b = null
(a == null) - (b == null) || -(a < b) || +(a > b) /*
└───────── 0 ─────────┘ └─ -0 ─┘ └─ 0 ─┘ */
//=> 0 a and b are equal
a = null, b = "a"
(a == null) - (b == null) || -(a < b) || +(a > b) /*
└───────── 1 ─────────┘ */
//=> 1 a is placed after b
a = "a", b = null
(a == null) - (b == null) || -(a < b) || +(a > b) /*
└───────── -1 ─────────┘ */
//=> -1 a is placed before b
a = "a", b = "a"
(a == null) - (b == null) || -(a < b) || +(a > b) /*
└───────── 0 ─────────┘ └─ -0 ─┘ └─ 0 ─┘ */
//=> 0 a and b are equal
a = "a", b = "b"
(a == null) - (b == null) || -(a < b) || +(a > b) /*
└───────── 0 ─────────┘ └─ -1 ─┘ */
//=> -1 a is placed before b
a = "b", b = "a"
(a == null) - (b == null) || -(a < b) || +(a > b) /*
└───────── 0 ─────────┘ └─ -0 ─┘ └─ 1 ─┘ */
//=> 1 a is placed after b
A less cryptic version could be written like so:
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => {
if (a == null && b != null) return 1; // a after b
if (a != null && b == null) return -1; // a before b
if (a < b) return -1; // a before b
if (a > b) return 1; // a after b
return 0; // equal
});
To apply an asc
/desc
direction, but keep the null
values at the back of the array, you can apply a modifier to the second part to inverse the sign (in case of a descending direction).
const modifiers = { asc: 1, desc: -1 };
const columnName = "Status";
const direction = "desc";
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => (
(a == null) - (b == null) // move null values to the back of the array
|| modifiers[direction] * (
-(a < b) // move `a` to the front if it's smaller than `b`
|| +(a > b) // move `a` to the back if it's greater than `b`
)
));
// without comments
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => (
(a == null) - (b == null) || modifiers[direction] * (-(a < b) || +(a > b))
));
Or:
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => {
if (a == null && b != null) return 1; // a after b
if (a != null && b == null) return -1; // a before b
if (a < b) return -1 * modifiers[direction]; // a before b
if (a > b) return 1 * modifiers[direction]; // a after b
return 0; // equal
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论