Search code examples
javascriptarrayssortinglodash

sortedIndex for reverse sorted array?


It seems lodash's sortedIndex expects a forward sorted array for its binary search to work. (e.g. [0,1,2,4])

Is there a way to used sortedIndexBy when the array is reverse sorted? (e.g. [4,2,1,0])?

> _.sortedIndex( [0,1,2,4], 3 )
> 3
> _.sortedIndex( [4,2,1,0], 3 )
> 4

To get this to work now, I have to reverse the array, find the sortedIndex, insert the new element, and then un-reverse the array.


Note -- need something which works for sorting strings as well as numbers.

['A','B','D'] into ['D','B','A'] and insert 'C'.


Solution

  • How about _.sortedIndexBy?

    Edited: For string comparison, String.prototype.charCodeAt() can help you convert it to Number, then the same logic can be applied.

    const arr1 = [0, 1, 2, 4];
    const arr2 = [4, 2 ,1, 0];
    
    console.log(_.sortedIndex(arr1, 3 ));
    // Similar, but with ranking function.
    console.log(_.sortedIndexBy(arr2, 3, function(x) {return -x;}));
    
    const charArr = ['D','B','A'];
    // Take the first char and convert to Number
    let index = _.sortedIndexBy(charArr, 'C', function(x) {
      // Type checks. (If you want it to be general to many types..
      if (typeof x === 'string') {
        return -x.charCodeAt(0);
      } else if (typeof x === 'number') {
        return -x;
      } // else ... for other types.....
    });
    
    console.log('To insert char C, put it to index: ', index);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>

    or by _.sortedIndex, it also has iteratee to rank before 4.0.0

        const arr1 = [0, 1, 2, 4];
        const arr2 = [4, 2 ,1, 0];
    
        console.log(_.sortedIndex(arr1, 3));
        console.log("Reversed order without ranking func: ",_.sortedIndex(arr2, 3));
        // Ranking function to inverse the order.
        console.log("Reversed order with ranking func: ",_.sortedIndex(arr2, 3, function(x) {return -x;}));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.3.1/lodash.min.js"></script>

    Thanks to pilau: The sortedIndex expects the array is forward sorted, so we can't just put the reverse sorted array and get arr.length - index, and in order to handle vary scenario, I think we need to do either

    • Reverse array -> get sorted index and put -> reverse it again. or
    • Get reversed copy by slice and reverse -> get sorted index and calculate by arr.length - index -> inserted to origin array.

    To achieve the expected result.