获取单个比较函数,以使用 Array.sort() 对 ASC 和 DESC 进行排序



我需要按属性price对象数组进行排序。

现在我有以下内容,可以按预期工作:

function orderByPriceASC(a,b) {
    return(
      a.price < b.price ? -1
      : a.price > b.price ? 1
        : 0
    );
  }
  function orderByPriceDESC(a,b) {
    return(
      a.price < b.price ? 1
      : a.price > b.price ? -1
        : 0
    );
  }
  function sortByPrice(order) {
    setProductList((prevState) => {
      const aux = Array.from(prevState);
      order === 'asc' ? aux.sort(orderByPriceASC) : aux.sort(orderByPriceDESC);
      return aux;
    });
  }

但是有没有办法让我构建它,以便我可以得到一个同时适用于 ASC 和 DESC 订单的比较函数?

像这样:

function orderByPrice(a,b,order) {
    return(
      a.price < b.price ?
        order === 'asc' ? -1 : 1
      : a.price > b.price ? 1
        order === 'asc' ? 1 : -1
        : 0
    );
  }

问题是我必须将该额外的参数发送到我认为不可能的Array.sort方法。也许带有一些包装器功能。

如何实现这一点?

您可以使用

multiplier并根据order变量将其设置为1-1。然后将其乘以 compareFunction 中的现有表达式(这里我假设pricenumber 类型(

let arr = [{ price: 2 },{ price: 1 },{ price: 3 }]
function sort(array, order) {
  const multiplier = order === "asc" ? 1 : -1;
  return array.sort((a, b) => multiplier * (a.price - b.price))
}
console.log(sort(arr, "asc"))
console.log(sort(arr, "desc"))

您可以定义函数并通过绑定它并发送自定义参数来传递它以进行排序,例如

let arr = [{price: 1},{price: 11},{price: 7},{price: 1},{price: 9},{price: 5},]
function orderByPrice(order, a,b) {
        if(a.price < b.price) {
            if(order === 'asc') {
                return -1;
            }
            return 1;
        } else if(a.price > b.price){
            if(order === 'asc') {
                return 1;
            }
            return -1
        }
        return 0;
      }
    
console.log(arr.sort(orderByPrice.bind(this, 'asc')))
console.log(arr.sort(orderByPrice.bind(this, 'desc')))

你可以这样做:

function flip(f) {
    return function (a, b) {
        return f(b, a);
    };
}
function orderByPriceASC(a,b) {
    return (
        a.price < b.price ? -1 :
        a.price > b.price ? 1 :
        0
    );
}
function sortByPrice(order) {
    setProductList((prevState) => {
        const aux = Array.from(prevState);
        aux.sort(order === 'asc' ? orderByPriceASC : flip(orderByPriceASC));
        return aux;
    });
}

这样,您就不需要单独的orderByPriceDESC函数,也不必添加任何额外的参数。

你可以用 Array.sort 和 Array.slice 做这样的事情:

let arr = [{ price: 2 },{ price: 1 },{ price: 3 }]
let sortBy = (arr, prop, dir=null) => 
  arr.slice().sort((a,b) => (a[prop] - b[prop]) * (dir ? -1 : 1))
console.log(sortBy(arr, 'price'))
console.log(sortBy(arr, 'price', 'desc')) // <-- any truthy value for `desc`

你必须使用 Array.slice 来克隆数组,因为 Array.sort 确实会改变数组,并且你需要一个pure函数。从文档中:

排序数组。请注意,数组已就地排序,没有副本 是做出来的。

此外,如果您使用的是 lodash,则已经有一个 _.orderBy 函数,该函数还允许对多个道具等进行排序:

let arr = [{ price: 2 },{ price: 1 },{ price: 3 }]
console.log(_.orderBy(arr, 'price'))
console.log(_.orderBy(arr, 'price', 'desc'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

您必须让函数返回一个函数,该函数接受方向作为参数,然后将其传递到内部函数中。我不喜欢动态类型语言中的标志,但它会是这样的:

function orderByPrice(direction) { // either 'ASC' or 'DESC
  return function (a, b) {
    if (direction === 'DESC') {
      const temp = a;
      a = b
      b = temp;
    }
    return (
      a.price < b.price ? -1
        : a.price > b.price ? 1
          : 0
    );
  }
}

然后实现将是

  function sortByPrice(direction) {
    setProductList((prevState) => {
      return Array.from(prevState).sort(orderByPrice(direction));
    });
  }

最新更新