Sorting Array with JavaScript reduce function

后端 未结 9 804
南方客
南方客 2020-12-01 17:49

Often I study some JavaScript interview questions, suddenly I saw a question about usage of reduce function for sorting an Array, I r

相关标签:
9条回答
  • 2020-12-01 18:32

    Here's an (imo) more elegant version of Jonas W's insertion sort solution. The callback just builds a new array of all lower values, the new one and all higher values. Avoids using explicit loops or indices, so it's easier to see at a glance that it works correctly.

    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, []))

    0 讨论(0)
  • 2020-12-01 18:33

    A terrible sorting algorithm can be written in a one liner with ES6:

    const sorter = (xs, x) => xs.slice(-1)[0] >= x ? [x, ...xs] : [...xs, x];
    

    If the present element is larger or equal the last element of the previously sorted list it is appended to the end, otherwise to the beginning.

    [3,4,1].reduce(sorter,[]).reduce(sorter,[])
    
    //returns [1,3,4]
    

    It takes several applications to its return to sort anything but the most simple arrays.

    But it will eventually get there. That calls for a recursion!

    const arr = [91,4,6,24,8,7,59,3,13,0,11,98,54,23,52,87,4];
    
    const sorter2 =(as) => as.reduce(
      (xs, x) => x >= xs.slice(-1)[0] ? [...xs, x] 
        : xs[0] < x ? sorter2([x, ...xs])
        : [x, ...xs],
      [],
    );
    
    const result = sorter2(arr);
    
    console.log(result.join(', '));

    When the present value is larger than the last value of already processed array it is appended. If it is smaller than the first element it is prepended. Only if it is neither before or after the the present value and the accumulated array are sorted again by a recursive call. The method should be equivalent to an insertion sort (please comment!).

    0 讨论(0)
  • 2020-12-01 18:34

    Array.sort mutates the array where using Array.reduce encourages a pure function. You could clone the array before sorting.

    I believe this question is designed to get you thinking differently by enforcing constraints. It tests your knowledge of how reduce works and as the answers show there are many ways to skin a cat. It'll show your personal flavour of js in solving this.

    I chose to use Array.findIndex and Array.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, []);
    

    Testing with the sample input produces

    arr.reduce(sortingReducer, [])
    // (17) [0, 3, 4, 4, 6, 7, 8, 11, 13, 23, 24, 52, 54, 59, 87, 91, 98]
    
    0 讨论(0)
  • 2020-12-01 18:40

    Here is an example of the sorting an array in descending order using reduce function.

    what is the initialValue of reduce function

    In this below function the initial value is the [] which is passed as thisArg in the reduce function.

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

    So basically an empty array is passed and the elements will be be pushed to this array

    The accumulator here is the empty array.

    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)

    0 讨论(0)
  • 2020-12-01 18:43

    Though, reduce is not ideally meant for the sorting. The following solution is just like a forEach or any loop function trying to be achieved with Array.reduce function.

    var arr = [91,4,6,24,8,7,59,3,13,0,11,98,54,23,52,87,4];
    
    arr = arr.reduce(function(acc,val){
      
      if(acc.length) {
        var temp = [];
        while(acc[acc.length -1] > val) {
          temp.push(acc.pop());
        } 
        acc.push(val);
        while(temp.length) {
          acc.push(temp.pop());
        }
      } else {
        acc.push(val);  
      }
      return acc;
      
    }, []);
    
    console.log(arr);

    Please note, you can use the native function Array.sort for sorting and can also have your own custom sort function where you can define your own sorting algorithm.

    0 讨论(0)
  • 2020-12-01 18:45

    You could use some functions for getting an array if not an array is supplied, a function which returns a sorted array by taking two parameters and a sort callback which includes the above by using another reduce method for getting a part result of a sorted array.

    const
        getArray = a => Array.isArray(a) ? a : [a],
        order = (a, b) => a < b ? [a, b] : [b, a],
        sort = (a, b) => getArray(a).reduce((r, v) => r.concat(order(r.pop(), v)), [b]),
        array = [91, 4, 6, 24, 8, 7, 59, 3, 13, 0, 11, 98, 54, 23, 52, 87, 4];
    
    console.log(array.reduce(sort));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    0 讨论(0)
提交回复
热议问题