使用 JavaScript 减少函数对数组进行排序

IT技术 javascript algorithm sorting reduce
2021-02-24 05:05:33

经常研究一些面JavaScript试题,突然看到一个关于reduce函数排序an的用法的问题Array,我在MDN上看过,在一些medium文章中也看到了它的用法,但是排序anArray太有创意了:

const arr = [91,4,6,24,8,7,59,3,13,0,11,98,54,23,52,87,4];

我想了很多,但我不知道如何回答这个问题,reduce call back函数必须如何是什么initialValuereduce功能?什么是accumulatorcurrentValuecall back的作用reduce

最后,这种方式是否比其他排序算法有一些好处?或者改进其他算法有用吗?

6个回答

在这里使用 reduce 是没有意义的,但是您可以使用一个新数组作为累加器并对所有元素进行插入排序:

array.reduce((sorted, el) => {
  let index = 0;
  while(index < sorted.length && el < sorted[index]) index++;
  sorted.splice(index, 0, el);
  return sorted;
}, []);

这是没有减少的版本

array.sort((a, b) => a - b);

现在有一些编写 reducer 的一般提示:

减少回调函数必须如何?

您要么采用累加器的方法,然后减速器应根据当前元素对累加器应用修改并返回它:

(acc, el) => acc

或者,如果 accumulator 和元素具有健全的类型并且在逻辑上是相等的,则不需要区分它们:

 (a, b) => a + b

reduce 函数的初始值是多少?

你应该问自己“当它应用于空数组时,什么应该减少回报?”

现在最重要的是:什么时候使用reduce?(海事组织)

如果您想将数组的值归结为一个值或对象

Array.sort改变数组,其中 usingArray.reduce鼓励纯函数。您可以在排序之前克隆数组。

我相信这个问题旨在通过强制约束让您以不同的方式思考。它测试您对reduce工作原理的了解,正如答案所示,有很多方法可以给猫剥皮。它会在解决这个问题时展示你个人的 js 风格。

我选择使用Array.findIndexArray.splice

const sortingReducer = (accumulator, value) => {
  const nextIndex = accumulator.findIndex(i => value < i );
  const index = nextIndex > -1 ? nextIndex : accumulator.length;
  accumulator.splice(index, 0, value);
  return accumulator;
}

const input = [5,4,9,1];
const output = input.reduce(sortingReducer, []);

使用样本输入进行测试会产生

arr.reduce(sortingReducer, [])
// (17) [0, 3, 4, 4, 6, 7, 8, 11, 13, 23, 24, 52, 54, 59, 87, 91, 98]

这是Jonas W 的插入排序解决方案的(imo)更优雅的版本回调只是构建一个包含所有较低值、新值和所有较高值的​​新数组。避免使用显式循环或索引,因此更容易一目了然地看到它是否正常工作。

const insertValue = (arr, value) =>
  [...arr.filter(n => n <= value), value, ...arr.filter(n => n > value)]

const testArr = [91, 4, 6, 24, 8, 7, 59, 3, 13, 0, 11, 98, 54, 23, 52, 87, 4]

console.log(testArr.reduce(insertValue, []))

在这个可能的疑难杂症:任何NaN数组中的条目将被删除,因为NaN既不是<= value> value显然,NaN在 OP 的例子中没有,而是一个特例,只是指出它。
2021-05-02 05:05:33
@TJCrowder 谢谢,不知道。我不会修改代码,但我想n <= value || Number.isNaN(n)会处理它。或更换n <= value!(n > value)以确保没有特殊情况下,可能会打破它。
2021-05-06 05:05:33

这是sorting使用reduce函数按降序排列数组的示例

什么是reduce函数的initialValue

在这个下面的函数中,初始值是在reduce函数中[]传递的thisArg

 array.reduce(function(acc,curr,currIndex,array){
        //rest of the code here
        },[]//this is initial value also known as thisArg)

所以基本上传递了一个空数组,元素将被推送到这个数组

这里的累加器是空数组。

const arr = [91, 4, 6, 24, 8, 7, 59, 3, 13, 0, 11, 98, 54, 23, 52, 87, 4];
var m = arr.reduce(function(acc, cur) {
  // this arrVar will have the initial array
  let arrVar = arr;
  // get the max element from the array using Math.max
  // ... is spread operator
  var getMaxElem = Math.max(...arrVar);
  // in the accumulator we are pushing the max value
  acc.push(getMaxElem);
  // now need to remove the max value from the array, so that next time it 
  // shouldn't not be considered
  // splice will return a new array
  // now the arrVar is a new array and it does not contain the current
  // max value
  arrVar = arrVar.splice(arrVar.indexOf(getMaxElem), 1, '')
  return acc;
}, []);
console.log(m)

@Andres 非常简单!做就是了m.reverse()
2021-04-29 05:05:33
asc订单应该做哪些改变?@brk
2021-05-15 05:05:33

reduce将自己限制在在线排序算法中,其中数组中的每个元素都被看到一次,而您现在不预先知道数组的长度(请注意,使用闭包可以为减少函数提供更多信息,但这种方式违背了问题)。

插入排序是一个明显而简单的例子;我不会详细说明实现,因为其他答案在这方面已经非常好。但是,您可以提及一些可能对面试官非常积极的优化:

  • 使用二分查找找到插入点可以将一个插入步骤的复杂度从 O(n) 降低到 O(log n)。这称为二元插入排序:比较的总数将从 O(n^2) 到 O(n log n)。这不会更快,因为真正的成本是由于“拼接”输出数组,但如果您进行了昂贵的比较(例如,对长字符串进行排序),它可能会有所作为。

  • 如果对整数进行排序,则可以使用基数排序并使用reduce 实现线性在线排序算法。这实现起来相当棘手,但非常适合减少。