Javascript 如何在我的sort by函数中处理空值?

Javascript 如何在我的sort by函数中处理空值?,javascript,json,reactjs,Javascript,Json,Reactjs,我有一个React表,它具有按desc和asc值排序的标题。 它将字符串值解析为数字以进行排序。但是,当我的numeric(x)函数在我的数据集中遇到null值时,它无法传递 以下是错误:TypeError:无法读取null的属性“slice” 下面是我的函数,我还向我的Comparator()添加了如何实现numeric排序的代码 function numeric(x) { const val = parseFloat(x); if (isNaN(val)) { r

我有一个React表,它具有按desc和asc值排序的标题。 它将字符串值解析为数字以进行排序。但是,当我的
numeric(x)
函数在我的数据集中遇到
null
值时,它无法传递

以下是错误:
TypeError:无法读取null的属性“slice”

下面是我的函数,我还向我的
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
}
我的表格示例使用了所有这些拼凑在一起的函数:

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>
        </>
    );
}
导出默认函数TableContent(道具)
{
const[orderDirection,setOrderDirection]=useState('asc');
常量[valueToOrderBy,setValueToOrderBy]=useState('symbol');
const{data}=props;
常量handleRequestSort=(事件、属性)=>
{
常量isAscending=(valueToOrderBy==属性和医嘱方向===='asc')
setValueToOrderBy(属性)
setOrderDirection(正在搜索“描述”:“asc”)
}
返回(

您可以尝试以下方法:

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;
      }
    }
  }

还不清楚您的排序函数是什么。
Array.prototype.sort()
期望
比较器以

function Comparator(a, b, /* no `orderBy` here! */) { ... }

并在
a
b
中传递数组的项,而不是对同一数组的两个引用。因此,您在这个问题中编写的代码看起来是错误的

但这可能只是一个复制粘贴错误,所以我们假设您使用的是标准的
Array.prototype.sort()

if(a==null)返回1
if(b==null)返回-1
我们应该这样做:

函数数值(x){
const val=parseFloat(x);
if(伊斯南(瓦尔)){
返回parseFloat(x.slice(1));
}否则{
返回val;
}
}
函数下降比较器(a,b)//删除了`orderBy`
{
如果(a==null)返回1
if(b==null)返回-1
常量numericA=numeric(a);//已删除[orderBy]
常量numericB=numeric(b);//已删除[orderBy]
if(numericBnumericA){
返回1
}
返回0
}
常量测试_arr=[null,1,null,'3%',0,'2',“$4”,null]
console.log([…test\u arr].sort(下降比较器))
//下面是如何实现删除的`orderBy`arg的行为
常量递增比较器=(a,b)=>递减比较器(b,a)
console.log([…test\u arr].sort(ascendingComparator))
//或者简单地使用`reverse()`
//或者,如果您希望在和处使用'null',在本例中也是如此,那么
常数递增比较器2=(a,b)=>{
如果(a==null)返回1
if(b==null)返回-1
返回下降比较器(b,a)
}

console.log([…test\u arr].sort(ascendingComparator2))
挑战在于基于列名和方向使用相同的函数对数字或文本进行排序。困难在于确保我们处理数字或文本…以应用正确的
.sort()
回调

此外,还有两件事需要考虑:

  • 某些字符串可能需要“重新格式化”为数字
  • 有些值可能是
    null
    ,并且应该总是在排序结束时结束

好的!首先,让我们来看看第一个函数:
sortedRowInformation(data, getComparator(orderDirection, valueToOrderBy)).map(...)
sortedRowInformation
看起来确实像是嵌套在
.sort()
函数中的
.sort()
函数…在
stabilizedRowArray
子数组上应用了两个
.map()

我必须承认我马上就放弃了它。我假设了预期的结果,因为它有一个很好的描述性名称,第一个参数是
数据

第二个参数…其中
getComparator()
是一个函数调用,两个组件状态属性作为参数。它返回两个可能的函数(lol,同一个函数的求值前面有或没有减号…)。因此,调用该
下降比较器
函数再次调用另一个函数
numeric()
,而我们的
null
问题就在这里

所有这些过程只返回
-1
0
1
,作为
sortedRowInformation()
…的第二个参数,这是基本的
.sort()
内部作业

仅仅描述这一过程就应该引起高度重视。您很好地将一切都复杂化了。


解决方案 以下是我从另一端开始的解决方案说明:
numeric()
函数可以作为一个函数进行隔离。但这正是您遇到困难的地方,因为上面3个函数中都有
null
值……因此,如果我们将
null
值放在该逻辑之外,并始终假定为非null值,该怎么办

因此,现在我们决定不存在
null
值,我们可以更轻松地测试它们的数字或字符串。无论如何,有一种特殊情况,在删除
$
和comas(千位分隔符)时,字符串最终可以成为数字

我提出了这个自定义的
isNumeric()
函数:

function isNumeric(x) {
  let value = !isNaN(x) ? x: parseFloat(x.replace(/[\$,]/g, ""))
  return {isNum:!isNaN(value), value}
}
该函数返回一个包含布尔值和“已处理”值的对象:一个数字或
NaN

现在…回到排序的起点,这里有一个对
数据进行排序的函数

function sortAll(data, orderDirection, valueToOrderBy) {
  
  // Filter the nulls in an array and the rest in another
  let nulls = data.filter((item) => item[valueToOrderBy] == null)
  let toSort = data.filter((item) => item[valueToOrderBy])
  
  // Sort the non-null values
  let sorted = toSort.sort((a, b) => {
    
    // Check if both values are numeric
    let aa = isNumeric(a[valueToOrderBy])
    let bb = isNumeric(b[valueToOrderBy])
    
    // If numerics
    if (aa.isNum && bb.isNum) {
      return aa.value - bb.value
    }
    
    // If strings
    return (a[valueToOrderBy]).toLowerCase() > (b[valueToOrderBy]).toLowerCase() ? 1 : -1;
  });

  // The sorting direction
  if (orderDirection === "desc") {
    sorted.reverse();
  }
  
  //  Add the nulls at the end of the returned array
  return sorted.concat(nulls);
}
因此,在您的React组件退货中应用它是:

sortAll(data, orderDirection, valueToOrderBy).map(...)
而不是:

sortedRowInformation(data, getComparator(orderDirection, valueToOrderBy)).map(...)
完全放弃这些函数:
sortedRowInformation
getComparator
downingcomparator
并用my
isNumeric
替换
numeric

下面是一个例子,我用一些feak
数据测试了排序案例


如果它不能在所有情况下都使用您的
数据
…至少,它更容易改进。

什么是示例输入
sortedRowInformation(data, getComparator(orderDirection, valueToOrderBy)).map(...)