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

时间:2019-05-29 17:05:15

标签: javascript

我需要通过属性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方法中,我认为这是不可能的。也许有一些包装功能。

如何实现?

6 个答案:

答案 0 :(得分:1)

您可以定义函数并通过绑定并发送自定义参数(如

)将其传递给排序

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')))

答案 1 :(得分:1)

您可以使用multiplier并根据1变量将其设置为-1order。然后将其乘以compareFunction内部的现有表达式(这里假设price的类型为number

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"))

答案 2 :(得分:0)

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

window

然后将实现

function sortByPrice(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
    );
  }
}

答案 3 :(得分:0)

您可以这样做:

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函数,也不必添加任何额外的参数。

答案 4 :(得分:0)

您可以使用Array.sortArray.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函数。来自documentation

  

已排序的数组。请注意,数组是按顺序排序的,没有副本   制成。

此外,如果您正在使用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>

答案 5 :(得分:-1)

尝试

function orderByPrice(a, b, order) {

  return order === 'desc'
   ? a && b && b.price - a.price
   : a && b && a.price - b.price
}

const b = [
   { price: 4},
  { price: 5},
  { price: 6}
]

function orderByPrice(a, b, order) {

      return order === 'desc'
       ? a && b && b.price - a.price
       : a && b && a.price - b.price
    }

console.log(b.sort((a, b) => orderByPrice(a, b, 'desc')))