如何在MUI数据网格中使用自定义排序算法对包含英文、日文条目和空值的列进行排序



我有一个MUI数据网格。我想为列创建一个自定义排序算法,它可以覆盖MUI提供的默认选项。我的数据字段有英文、日文数据以及空/null值。我期望的输出是显示列,按以下升序排列-

  1. A-Z英语
  2. 任何顺序的剩余Null和日语条目

下降

  1. Z-A
  2. 任何顺序的剩余Null和日语条目

我的代码如下

import * as React from "react";
import { DataGrid } from "@material-ui/data-grid";
const handleCellClick = (param, event) => {
console.log(param);
console.log(event);
if (param.colIndex === 2) {
event.stopPropagation();
}
};
const handleRowClick = (param, event) => {
console.log("Row:");
console.log(param);
console.log(event);
};
const columns = [
{
field: "id",
headerName: "ID",
width: 70
},
{
field: "firstName",
headerName: "First Name",
width: 130,
renderCell: (cellValues) => {
return (
<div
style={{
color: "blue",
fontSize: 18,
width: "100%",
textAlign: "right"
}}
>
{cellValues.value}
</div>
);
}
},
{ field: "lastName", headerName: "Last Name", width: 130 },
{
field: "age",
headerName: "Age",
type: "number",
//width: 90,
minWidth: 90,
flex: 1
//align: "left"
},
{
field: "fullName",
headerName: "Full name",
description: "This column has a value getter and is not sortable.",
sortable: false,
minWidth: 160,
flex: 2,
//width: 160,
valueGetter: (params) => {
return `${params.getValue(params.id, "firstName") || ""} ${
params.getValue(params.id, "lastName") || ""
}`;
}
}
];
const rows = [
{ id: 1, lastName: "Snow", firstName: "Jon", age: 35 },
{ id: 2, lastName: "Lannister", firstName: "Amy", age: 42 },
{
id: 3,
lastName: "IGOTAREALL",
firstName: "Jaime",
age: 45
},
{ id: 4, lastName: "Stark", firstName: "Arya", age: 16 },
{ id: 5, lastName: "Targaryen", firstName: "Daenerys", age: 12 },
{ id: 6, lastName: "Melisandre", firstName: "Jane", age: 15 },
{ id: 7, lastName: "榎原", firstName: "しよう", age: 44 },
{ id: 8, lastName: "田中", firstName: "田畑", age: 36 },
{ id: 9, lastName: "瀬奈", firstName: "健治", age: 65 }
];
export default function DataGridDemo() {

return (
<div style={{ height: 500, width: "100%" }}>
<DataGrid
rowHeight={50}
className={"hello"}
rows={rows}
columns={columns}
pageSize={10}
checkboxSelection
onCellClick={handleCellClick}
onRowClick={handleRowClick}
/>
</div>
);
}

它看起来像下面的(沙箱(。您可以自定义isEnglish()isNull()实用程序函数以满足您的需求,在Full name列的情况下,如果您愿意,您可以构建完整的${firstName} ${lastName}字符串进行比较。

const columns = [
{
field: "lastName",
headerName: "Last Name",
width: 130,
sortComparator: (v1, v2) => {
const isEnglish = (s) => /^[A-Za-z0-9]*$/.test(s);
const isNull = (s) => (s == undefined || s.trim() === '');
return (isNull(v1) || !isEnglish(v1)) - (isNull(v2) || !isEnglish(v2)) || v1.localeCompare(v2)
}
},
{
field: "fullName",
headerName: "Full name",
minWidth: 160,
flex: 2,
//width: 160,
valueGetter: (params) => {
return `${params.getValue(params.id, "firstName") || ""} ${params.getValue(params.id, "lastName") || ""
}`;
},
sortComparator: (v1, v2, param1, param2) => {
const isEnglish = (s) => /^[A-Za-z0-9]*$/.test(s);
const isNull = (s) => s == undefined || s.trim() === '';
const a = param1.api.getCellValue(param1.id, 'firstName');
const b = param2.api.getCellValue(param2.id, 'firstName');
return (isNull(a) || !isEnglish(a)) - (isNull(b) || !isEnglish(b)) || a.localeCompare(b)
}
}
]

编辑

数据网格采用对称排序,因此只是反转"desc"的逻辑。为此,您需要通过检测排序方向并手动反转OR语句中的初始值来进行干预,以继续排序到底。您可以通过传递给比较器的param参数之一访问当前状态:

const isDesc = param1.api.state.sorting.sortModel[0].sort === "desc";

然后,您可以使用此布尔值来调整第一个OR值:

((isNull(v1) || !isEnglish(v1)) - (isNull(v2) || !isEnglish(v2))) * (isDesc ? -1 : 1) 
|| v1.localeCompare(v2)

完整的解决方案可能如下:

{
field: "lastName",
headerName: "Last Name",
width: 130,
sortComparator: (v1, v2, param1) => {
const isEnglish = (s) => /^[A-Za-z0-9]*$/.test(s);
const isNull = (s) => s == undefined || s.trim() === "";
const shouldSortToEnd = (s) => isNull(s) || !isEnglish(s);
const isDesc = param1.api.state.sorting.sortModel[0].sort === "desc";
return (
(shouldSortToEnd(v1) - shouldSortToEnd(v2)) * (isDesc ? -1 : 1) ||
v1.localeCompare(v2)
);
}
},

这是基于使用OR短路的sort()

const rows = [
{ id: 1, lastName: "Snow", firstName: "Jon", age: 35 },
{ id: 2, lastName: "Lannister", firstName: "Amy", age: 42 },
{ id: 3, lastName: "IGOTAREALL", firstName: "Jaime", age: 45 },
{ id: 4, lastName: "Stark", firstName: "Arya", age: 16 },
{ id: 5, lastName: "Targaryen", firstName: "Daenerys", age: 12 },
{ id: 6, lastName: null, firstName: "Jane", age: 15 },
{ id: 7, lastName: "榎原", firstName: "しよう", age: 44 },
{ id: 8, lastName: "田中", firstName: "田畑", age: 36 },
{ id: 9, lastName: "瀬奈", firstName: "健治", age: 65 }
];
rows.sort((a, b) => {
const isEnglish = (s) => /^[A-Za-z0-9]*$/.test(s);
const isNull = (s) => s == undefined || s === '';
a = a.lastName;
b = b.lastName;
return (isNull(a) || !isEnglish(a)) - (isNull(b) || !isEnglish(b)) || a.localeCompare(b);
});
console.log(rows.map(({ lastName }) => lastName).join(', '));

参见:

  • 如何按多个字段对对象数组进行排序
  • Javascript查找是否仅英文字母

最新更新