【问题标题】:Two callbacks as argument for Array.sort(), rather than Array.sort().sort() [duplicate]两个回调作为 Array.sort() 的参数,而不是 Array.sort().sort() [重复]
【发布时间】:2019-10-05 10:50:36
【问题描述】:

我正在尝试返回已排序产品的列表:

return products.sort(getSortFunc(activeSortId))

每个activeSortId 对应一个排序回调函数,通过调用getSortFunc 检索该函数。我有三个排序函数:sortByPriceAscsortByPriceDescsortByDate

问题:当用户 sortByPriceDesc 后跟 sortByDate 时,结果(逻辑上)仍然按降序排列。但是,我希望它按升价排序。我可以通过链接排序函数(return products.sort(a).sort(b).sort(c))来解决这个问题,但是如果我不知道顺序怎么办?:

我想知道是否可以通过调用例如解决它sortByPriceAsc 在函数 sortByDate 中,还是类似的东西?下面是一个简化的尝试,但显然它不起作用,因为调用 sortByPriceAsc 不会修改任何内容:

sortByPriceAsc: (a, b) => a.price - b.price,
sortByDate: (a, b) => {
  this.sortByPriceAsc()
  return b.date - a.date
}

很高兴获得任何帮助或一般批评。

【问题讨论】:

  • I could solve this by chaining the sorting function - 通常不会,因为不能保证sort 是稳定的。

标签: javascript sorting callback


【解决方案1】:

一个选项是有一个持久变量来指示最后的 asc/dec 排序顺序。然后,在sortByDate 中,每当调用它时,检查该变量以确定在两个日期相同的情况下返回什么:

const arr = [
  { date: 1, price: 5 },
  { date: 2, price: 10 },
  { date: 2, price: 20 },
  { date: 3, price: 30 },
  { date: 3, price: 40 },
  { date: 4, price: 50 },
];

let lastWasAsc = false;
const sorts = {
  sortByPriceAsc: (a, b) => a.price - b.price,
  sortByDate: (a, b) => {
    return b.date - a.date || (
      lastWasAsc
      ? a.price - b.price
      : b.price - a.price
    );
  }
};

// When sorting by ascending order, set lastWasAsc to true:
lastWasAsc = true;
arr.sort(sorts.sortByPriceAsc);

// Then, later:
arr.sort(sorts.sortByDate);
console.log(arr);

比较,当lastWasAscfalsesortByDate 被调用:

const arr = [
  { date: 1, price: 5 },
  { date: 2, price: 10 },
  { date: 2, price: 20 },
  { date: 3, price: 30 },
  { date: 3, price: 40 },
  { date: 4, price: 50 },
];

let lastWasAsc = false;
const sorts = {
  sortByPriceAsc: (a, b) => a.price - b.price,
  sortByDate: (a, b) => {
    return b.date - a.date || (
      lastWasAsc
      ? a.price - b.price
      : b.price - a.price
    );
  }
};

// Then, later:
arr.sort(sorts.sortByDate);
console.log(arr);

请记住,arr.sort(cb1).sort(cb2)不一定必须考虑由 cb1 排序的任何内容 - 排序算法不一定稳定,因此不同实现的行为会有所不同(因此 .sort(..).sort(不应该使用)。

(一种稳定的排序算法is when,当两个元素由于具有相同的“权重”而在结果中被确定为彼此相邻时,它们在输出中的顺序与它们在输入中的顺序相同. 这在 Javascript 中无法保证。虽然 ES2019 要求 Array#sort 稳定,但并非所有实现都符合这一点。)

【讨论】:

  • 大声朗读return b.date - a.date || (lastWasAsc ? a.price - b.price : b.price - a.price); 让它看起来像是按日期或按价格排序,我想不是这样吗?所以基本上我们按日期排序,然后如果它是最后一个升序,还要改变价格的顺序吗?我只是想了解sortByDate 的作用。非常感谢您的回复!
  • 那个条件运算符的意思是:如果日期差为0,则返回以下内容:如果lastWasAsc,则返回a.price - b.price,否则返回b.price - a.price。它仅按两个项目之间的相对价格排序如果这两个项目的日期没有差异。
  • 我不完全明白。如果它只做这部分:(lastWasAsc ? a.price - b.price : b.price - a.price) 如果日期差为 0,那么它只在日期相同时才这样做?您的示例中没有相同的日期,因此这部分代码似乎永远不会执行。
  • 示例中有两对日期相同的对象:{ date: 2, price: 10 }, { date: 2, price: 20 }{ date: 3, price: 30 }, { date: 3, price: 40 }。在第一个 sn-p 中,价格较低的对象首先出现,而第二个 sn-p 则相反——这是您问题的症结所在(sn-ps 看起来可以产生您想要的功能,对吗?) .
  • 您的代码似乎做了正确的事情,但我对它的理解还不够,无法重现它。我实际上在问题中混淆了一些函数名称。我想要的是在应用日期函数时按升序排序的结果(反之亦然)。我似乎无法调整您的条件语句来实现这一目标..
猜你喜欢
  • 2015-04-10
  • 2019-09-12
  • 2011-10-02
  • 2020-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多