如何在排序依据函数中处理空值?

woo*_*oof 1 javascript json reactjs

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

这是错误:TypeError: Cannot read property 'slice' of null

下面是我的函数,我还添加了有关如何实现numeric排序Comparator()的代码

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
}
Run Code Online (Sandbox Code Playgroud)

我应该如何处理数字函数中的空值?实际上,当按 asc 和 desc 排序时,它们应该被忽略并放置在啄序的底部。

编辑:输入 x 的示例数据类型:

  • 10
  • 10%
  • 10 美元
  • .1
  • abc(字符串字符)

如果不小心,Null 值可能会在对数据进行排序时充当 a 0。需要注意的是,Null 仅意味着没有可用数据,不应为它们提供数值。

编辑编辑:有关我的比较器和排序功能的重要信息

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])
}
Run Code Online (Sandbox Code Playgroud)

我的表的一个示例使用了所有这些函数的组合:

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>
        </>
    );
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Lou*_*tte 6

挑战在于根据列名称和方向对具有相同功能的数字或文本进行排序。困难在于确保我们处理数字或文本......以应用正确的.sort()回调。

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

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

好的!首先,让我们从第一个函数开始浏览一下您的函数:
sortedRowInformation(data, getComparator(orderDirection, valueToOrderBy)).map(...)
Run Code Online (Sandbox Code Playgroud)

sortedRowInformation确实看起来像一个.sort()函数嵌套在一个.sort()函数中...两个.map()应用在一个stabilizedRowArray子数组上...

我不得不承认我立刻就把它扔掉了。我通过其相当具有描述性的名称和第一个参数是data.

第二个参数...其中getComparator()是以两个组件状态属性作为参数的函数调用。这会返回两个可能的函数(哈哈,相同的函数在其计算前面有或没有减号......)。因此,再次调用该descendingComparator函数会调用另一个函数numeric()来解决我们的null问题。

所有这些过程只是返回-10或者1用作sortedRowInformation()...的第二个参数,这是基本的.sort()内部工作。

仅仅描述这个过程就应该竖起一个大旗。你把一切都搞得太复杂了。


解决方案

以下是我从另一端开始的解决方案解释:

numeric()函数可以作为一个函数来隔离。但这就是你遇到困难的地方,因为null上面的 3 个函数中的值......那么,如果我们将这些null值放在该逻辑之外并始终假设一个非空值呢?

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

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

function isNumeric(x) {
  let value = !isNaN(x) ? x: parseFloat(x.replace(/[\$,]/g, ""))
  return {isNum:!isNaN(value), value}
}
Run Code Online (Sandbox Code Playgroud)

该函数返回一个包含布尔值和“已处理”值的对象:数字或NaN.

现在...回到排序的起点,这里是一个对 进行排序的函数data

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);
}
Run Code Online (Sandbox Code Playgroud)

因此,将其应用到 React 组件返回中是:

sortAll(data, orderDirection, valueToOrderBy).map(...)
Run Code Online (Sandbox Code Playgroud)

代替:

sortedRowInformation(data, getComparator(orderDirection, valueToOrderBy)).map(...)
Run Code Online (Sandbox Code Playgroud)

直接丢弃这些函数:sortedRowInformation getComparatordescendingComparator并替换numeric为 my isNumeric

这是一个CodePen,我用一些 feak 测试了排序案例data


如果它还不能在所有情况下都适用于您的data……至少,改进会更容易。;)