[英]How to handle null values inside my sort by function?
I have a React table that has sortable headers by desc and asc values.我有一个 React 表,它具有按 desc 和 asc 值排序的标题。 It parses string values to numbers for sorting.
它将字符串值解析为数字以进行排序。 However, my
numeric(x)
function fails to deliver when it meets a null
value in my dataset.但是,我的
numeric(x)
function 在满足我的数据集中的null
值时无法交付。
Here is the error: TypeError: Cannot read property 'slice' of null
这是错误:
TypeError: Cannot read property 'slice' of null
Below is my function, and I also added code on how I implement numeric
to my Comparator()
for sorting下面是我的 function,我还添加了关于如何在
Comparator()
中实现numeric
以进行排序的代码
function numeric(x) {
const val = parseFloat(x);
if (isNaN(val)) {
return parseFloat(x.slice(1));
} else {
return val;
}
}
function descendingComparator(a, b, orderBy)
{
const numericA = numeric(a[orderBy]);
const numericB = numeric(b[orderBy]);
if (numericB < numericA){
return -1
}
if (numericB > numericA){
return 1
}
return 0
}
How should I handle nulls in my numeric function?我应该如何处理我的数字 function 中的空值? Realistically, they should be ignored and be placed at the bottom of the pecking order when sorting by asc and desc.
实际上,在按 asc 和 desc 排序时,它们应该被忽略并放在啄食顺序的底部。
EDIT: example data types for input x:编辑:输入 x 的示例数据类型:
If not careful, the Null values can act as a 0
when sorting data.如果不小心,Null 值在排序数据时可能会充当
0
。 It's important to note that Null simply means no data available, they should not be given a numerical value.需要注意的是,Null 仅仅意味着没有可用的数据,它们不应该被赋予数值。
EDIT EDIT: Important information about my Comparator and sorting functions编辑编辑:关于我的比较器和排序功能的重要信息
function getComparator(order, orderBy)
{
return order === "desc"
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy)
}
const sortedRowInformation = (rowArray, comparator) =>
{
const stabilizedRowArray = rowArray.map((el, index) => [el, index])
stabilizedRowArray.sort((a, b) =>
{
const order = comparator(a[0], b[0])
if (order !== 0) return order
return a[1] - b[1]
})
return stabilizedRowArray.map((el) => el[0])
}
An example of my table that uses all of these functions pieced together:我的表的一个例子,它使用了所有这些函数拼凑在一起:
export default function TableContent(props)
{
const [orderDirection, setOrderDirection] = useState('asc');
const [valueToOrderBy, setValueToOrderBy] = useState('symbol');
const { data } = props;
const handleRequestSort = (event, property) =>
{
const isAscending = (valueToOrderBy === property && orderDirection === 'asc')
setValueToOrderBy(property)
setOrderDirection(isAscending ? 'desc' : 'asc')
}
return (
<>
<TableContainer>
<Table>
<AdvancedStatsHeaders
data={data}
valueToOrderBy={valueToOrderBy}
orderDirection={orderDirection}
handleRequestSort={handleRequestSort}
/>
<TableBody>
{
sortedRowInformation(data, getComparator(orderDirection, valueToOrderBy))
.map((stock, index) => (
<TableRow key = {index} >
<TableCell>
{stock.symbol}
</TableCell>
<TableCell>
{stock.enterprisevalue}
</TableCell>
<TableCell>
{stock.enterprise_value_revenue}
</TableCell>
<TableCell>
{stock.revenuepershare}
</TableCell>
<TableCell>
{stock.debt_to_equity}
</TableCell>
<TableCell>
{stock.ebitda}
</TableCell>
<TableCell>
{stock.profitmargin}
</TableCell>
<TableCell>
{stock.price_to_sales}
</TableCell>
<TableCell>
{stock.price_to_book}
</TableCell>
<TableCell>
{stock.put_call_ratio}
</TableCell>
</TableRow>
))
}
</TableBody>
</Table>
</TableContainer>
</>
);
}
The challenge is about sorting numbers OR text with the same function, based on a column name and a direction.挑战在于根据列名和方向对具有相同 function 的数字或文本进行排序。 The difficulty is about making sure we deal with a number or with text... to apply the right
.sort()
callback.困难在于确保我们处理数字或文本......以应用正确的
.sort()
回调。
Additionally, there are two things to take in account:此外,还有两点需要考虑:
null
and should always must ends up at the end of the sorting.null
并且应该总是在排序结束时结束。 sortedRowInformation(data, getComparator(orderDirection, valueToOrderBy)).map(...)
That sortedRowInformation
really looks like a .sort()
function nested in a .sort()
function... With two .map()
applied on a stabilizedRowArray
sub-array...那个
sortedRowInformation
真的看起来像一个.sort()
function 嵌套在一个.sort()
function ... 两个.map()
应用于一个stabilizedRowArray
子阵列...
I have to admit I discarded it right away .我不得不承认我马上就把它扔掉了。 I assumed the expected result by its pretty descriptive name and the 1st argument being the
data
.我通过其漂亮的描述性名称和第一个参数来假设预期的结果
data
。
The second argument... Where getComparator()
is a function call with the two componant state properties as argument.第二个参数......其中
getComparator()
是一个 function 调用,其中两个组件 state 属性作为参数。 That returns two possible functions (lol, the same function with or without a minus sign in front of its evaluation...).这将返回两个可能的函数(大声笑,相同的 function 在其评估前有或没有减号......)。 So calling that
descendingComparator
function again calls another function numeric()
where our null
problem is.所以调用
descendingComparator
function 再次调用另一个function numeric()
我们的null
问题所在。
And all this process to just return -1
, 0
or 1
to be used as that second argument for sortedRowInformation()
... Which is the basic .sort()
internal job.所有这些过程只返回
-1
、 0
或1
用作sortedRowInformation()
的第二个参数......这是基本的.sort()
内部工作。
Just describing this process should raise a big flag.仅仅描述这个过程就应该引起很大的关注。 You nicely overcomplicated everything.
你很好地把一切都复杂化了。
The numeric()
function is okay to isolate as a function. numeric()
function 可以隔离为 function。 But that is where you had difficulties due to the null
values coming in 3 functions above... So what if we put the null
values aside from that logic and always assume a non-null value?但这就是您遇到困难的地方,因为
null
值出现在上面的 3 个函数中......那么如果我们将null
值放在该逻辑之外并始终假定非空值怎么办?
So now that we decided there is no null
values, we can test them more easily for number or string.所以现在我们确定没有
null
值,我们可以更轻松地测试它们的数字或字符串。 Anyway there is a special case where a string can finally be a number when removing the $
and comas (thousand separator).无论如何,有一种特殊情况,当删除
$
和逗号(千位分隔符)时,字符串最终可以是数字。
I came up with this custom isNumeric()
function:我想出了这个自定义 isNumeric
isNumeric()
function:
function isNumeric(x) { let value =?isNaN(x): x. parseFloat(x,replace(/[\$,]/g: "")) return {isNum,!isNaN(value), value} }
That function returns an object containing a boolean and a "processed" value: a number or NaN
. function 返回一个 object ,其中包含一个 boolean 和一个“已处理”值:一个数字或
NaN
。
Now... Getting back to the starting point for the sorting, here is a function to sort the data
:现在...回到排序的起点,这里有一个 function 来对
data
进行排序:
sortedRowInformation(data, getComparator(orderDirection, valueToOrderBy)).map(...)
So to apply it in your React component return is:所以将它应用到你的 React 组件返回是:
sortAll(data, orderDirection, valueToOrderBy).map(...)
instead of:代替:
sortedRowInformation(data, getComparator(orderDirection, valueToOrderBy)).map(...)
Squarely discard those functions: sortedRowInformation
, getComparator
and descendingComparator
and replace numeric
with my isNumeric
.直接丢弃这些函数:
sortedRowInformation
、 getComparator
和descendingComparator
并用我的isNumeric
替换numeric
。
Here is a CodePen where I tested the sorting cases with some feak data
.这是一个CodePen ,我在其中使用一些 feak
data
测试了排序案例。
If it does not already work in all cases with your data
... At least, it is way easier to improve.如果它不适用于您的
data
的所有情况......至少,它更容易改进。 ;) ;)
You can try something like below:您可以尝试以下方法:
function numeric(x,order) {
const val = parseFloat(x);
if(!x) {
return order === 'desc'? -1 : 1;
}
else {
if (isNaN(val)) {
return parseFloat(x.slice(1));
} else {
return val;
}
}
}
It's unclear what's your sorting function is.目前还不清楚你的排序 function 是什么。
Array.prototype.sort()
expects Comparator
in the form of Array.prototype.sort()
期望Comparator
的形式为
function Comparator(a, b, /* no `orderBy` here! */) { ... }
and passes items of an array in a
and b
, not two references to the same array.并在
a
和b
中传递数组的项目,而不是对同一数组的两个引用。 So the code your've wrote in this question looks wrong.所以你在这个问题中写的代码看起来是错误的。
But maybe that's just a copy-paste error, so let's assume that your're using the standard Array.prototype.sort()
.但也许这只是一个复制粘贴错误,所以让我们假设您使用的是标准的
Array.prototype.sort()
。 In this case在这种情况下
if( a === null ) return 1
if( b === null ) return -1
should do the trick:应该做的伎俩:
function numeric(x) { const val = parseFloat(x); if (isNaN(val)) { return parseFloat(x.slice(1)); } else { return val; } } function descendingComparator(a, b) // removed `orderBy` { if( a === null ) return 1 if( b === null ) return -1 const numericA = numeric(a); // removed [orderBy] const numericB = numeric(b); // removed [orderBy] if (numericB < numericA){ return -1 } if (numericB > numericA){ return 1 } return 0 } const test_arr = [null, 1, null, '3%', 0, '2', "$4", null] console.log([...test_arr].sort(descendingComparator)) // here's how you can implement behavior of removed `orderBy` arg const ascendingComparator = (a, b) => descendingComparator(b, a) console.log([...test_arr].sort(ascendingComparator)) // or simply use `reverse()` // or, if you want `null` at the and in this case too, then const ascendingComparator2 = (a, b) => { if( a === null ) return 1 if( b === null ) return -1 return descendingComparator(b, a) } console.log([...test_arr].sort(ascendingComparator2))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.