2

I'm trying to fully understand functional programming when sorting an array why does the original array change to the sorted array also? I want to check if the array is in ascending order.

let arr = [1,2,8,3,9,88,67];
let newArr = arr.sort((a,b) => a-b);
console.log(newArr);
console.log(arr);

I want to do something like....

if (arr === newArr) {
return true;
} else {
return false;
}

The original arr is also being sorted so it always is true, some guidance would be great thanks.

Carlos
  • 35
  • 1
  • 7

6 Answers6

1

That's just the way the sort operator was designed. It modifies the existing array, rather than creating a new array. If you want to create a new array, you can do it like this:

let arr = [1,2,8,3,9,88,67];
let newArr = arr.slice(); // creates a copy of the array
newArr.sort((a,b) => a-b);

console.log(newArr);
console.log(arr);
Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
0

Javascript array is an object, When 2 variables reference the same object, changing one would change the value of the other

let obj1 = {x:1, y:2};

let obj2 = obj1;

obj2.x = 3;

console.log(obj1);

You can sort it using

let arr = [1,2,8,3,9,88,67];
let newArr = arr.slice().sort((a,b) => a-b);
console.log(newArr);
console.log(arr);
marvel308
  • 10,288
  • 1
  • 21
  • 32
0

By assigning an object, you take the reference of the object, that means ecery change affects the same object.

For arrays, you could take "a shallow copy" of it with Array#slice and then map the check of the items.

var array = [1, 2, 8, 3, 9, 88, 67],
    sorted = array.slice().sort((a, b) => a - b),
    position = array.map((a, i) => a === sorted[i]);

console.log(sorted);
console.log(position);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

According to your question, you just need to identify

If the array is in ascending order

To do that just apply some simple logic and we do not want to compare it with a sorted array.

This is the speediest method since it will break the loop on wrong condition.

let arr = [1,2,8,3,9,88,67];
let is_sorted = true;

for(let i=0, length = arr.length; i < length - 1; i++){
  if(Number(arr[i]) > Number(arr[i+1])){
    is_sorted = false;
    break;
  }
}

console.log("Is Sorted: ", is_sorted);
Thusitha
  • 3,393
  • 3
  • 21
  • 33
  • this is the imperative version of the program described in my answer – nice work Thusitha – Mulan Sep 18 '17 at 19:04
0

This is an XY problem – ie, you want "... to check if the array is in ascending order" and you tried sorting (via Array.prototype.sort) and then you're checking the result using binary operator ==. The result isn't what you expect, so you ask about the sort instead of keeping the focus on your actual goal: checking for ascending order

A case for why you shouldn't sort

Imagine a large array of hundreds or thousands or items. Is the following array in ascending order?

isAscending ([ 5, 1, ... thousands more items ... ])
// => true or false ?

Of course it's false because 1 is less than 5; the array is not in ascending order. Did we have to sort the entire array to arrive at that answer? No, we only needed to look at the first 2 items (in this case) to know the answer is false

Other answers show using .slice to copy the input array – this is silly tho, because of course we don't have to copy an array to determine if it is in ascending order – it's a waste of time/space.

A case for why you shouldn't use ==

Well first, you can't, because of the following (in JavaScript)

[ 1, 2, 3 ] == [ 1, 2, 3 ]
// => false

So how would use == if you could? Maybe an approach would be to check if each element in the first array is equal to each array element in the second array. Ok, now imagine two large arrays of hundreds of thousands of items. Are the following two arrays equal?

[ 1, ... thousands of items ... ] == [ 2, ... thousands of items ... ]
// => true or false ?

We know they're not equal because 1 != 2 – it's the same case as the sorting; there's no sense in comparing the rest of the items because we already know the arrays are not equal

There's other ways to compare Arrays (and objects) in JavaScript, but we only have one input array, so there's no array to compare it to – this is another dead-end to the approach

Check if an array is in ascending order

Ok, so now that were done talking about array sorting and array equality in JavaScript, we can actually write a function that does what you intend it to do

const isAscending = ([x,y,...rest]) =>
  x === undefined                   // array is empty
    ? true
    : y === undefined               // single element array
      ? true
      : x > y                       // first element is larger than second
        ? false
        : isAscending ([y,...rest]) // check remaining elements

console.log (isAscending ([]))        // true
console.log (isAscending ([1]))       // true
console.log (isAscending ([1,3,5,7])) // true
console.log (isAscending ([5,1,3,7])) // false

Stack-safe recursion

But you have to be careful using recursion in JavaScript – input arrays of just a couple thousand elements could cause a stack overflow in the program above

Using a constant-space looping mechanism, we can rewrite isAscending in a way that works on arrays of any input size. The loop/recur interface gives us an opportunity to track any number/type of state variables, so this implementation also avoids the costly creation of many array slices (in rest parameter and spread argument syntax above)

const recur = (...args) =>
  ({ type: recur, args })
  
const loop = f =>
  {
    let acc = f ()
    while (acc.type === recur)
      acc = f (...acc.args)
    return acc
  }

const isAscending = xs =>
  xs.length < 2
    ? true
    : loop ((a = 0, b = 1) =>
        a === xs.length
          ? true
          : xs [a] > xs [b]
            ? false
            : recur (a + 1, b + 1)) // *
  
console.log (isAscending ([]))        // true
console.log (isAscending ([1]))       // true
console.log (isAscending ([1,3,5,7])) // true
console.log (isAscending ([5,1,3,7])) // false

* or recur (b, b + 1), which saves on addition operation per array element

Mulan
  • 129,518
  • 31
  • 228
  • 259
-1

The sort method applied to an array will modify the array itself. So it's logic to have the first array sorted and both arr and newArr will be equal.

To test if the array is in ascending order you may loop through it and check if there is and index i where arr[i+1] < arr[i]

let arr = [1,2,8,3,9,88,67];
let test=true;

for (var i = 1; i < arr.length; i++) {
    if(arr[i]<arr[i-1]) {
      test=false;
      break;
    }
    
}
console.log(test);
Temani Afif
  • 245,468
  • 26
  • 309
  • 415