2

While implementing a bubble sort algorithm I noticed that logging the array within an object produced a different result than logging it directly. Why?

function bubbleSort(arr) {
  let array = [...arr];
  let sorted = false;
  let round = 0;

  while (!sorted) {

    sorted = true;
    console.log({ array }); // this shows the already sorted array
    console.log(array); // this shows the array after one round of sorting

    for (let i = 0; i < array.length - 1 - round; i++) {
      if (array[i] > array[i + 1]) {
        [array[i], array[i + 1]] = [array[i + 1], array[i]];
        sorted = false;
      }
    }
    round++;
  }
  return array;
}

bubbleSort([1,4,6,3,45,78,9])
cccn
  • 929
  • 1
  • 8
  • 20
Nico
  • 105
  • 6
  • 3
    Because `array` is an array but `{array}` is an object with property `array`. By the time you expand the object, the code has already finished. – Felix Kling Nov 09 '19 at 16:39
  • @FelixKling I'm still a bit confused, why does the code finish before expanding the object? After each loop I'm both logging the array and logging an object with the same array in it. How can they be different? – Nico Nov 09 '19 at 16:55
  • @Nico The console shows "> Object { array: (4) [...] }" By the time you click to expand this line (i.e. the object) the code has completed and the array has been fully sorted. – Frazer Nov 09 '19 at 17:25
  • *"why does the code finish before expanding the object?"* Because the code is really fast and you are slow. I'd argue that it takes several hundred millisecond for you to expand the object after it was printed to the console. The code probably needs less than that. Keep in mind that objects (which includes arrays) are reference values. When you expand the object you see the value the array is right then and there. That's also what the little blue `i` next to it tells you. – Felix Kling Nov 09 '19 at 17:43

2 Answers2

2

Your statement is invalid.

This code shows both console.log are printing the same array every single round.

function bubbleSort(arr) {
  let array = [...arr];
  let sorted = false;
  let round = 0;

  while (!sorted) {

    sorted = true;
    console.log({ array }, `Round no. ${round}`); // this shows the already sorted array
    console.log(array, `Round no. ${round}`); // this shows the array after one round of sorting

    for (let i = 0; i < array.length - 1 - round; i++) {
      if (array[i] > array[i + 1]) {
        [array[i], array[i + 1]] = [array[i + 1], array[i]];
        sorted = false;
      }
    }
    round++;
  }
  return array;
}

bubbleSort([10,7,15,1]);

This is what I get when I execute this snippet

{
  "array": [
    10,
    7,
    15,
    1
  ]
} Round no. 0
[
  10,
  7,
  15,
  1
] Round no. 0
{
  "array": [
    7,
    10,
    1,
    15
  ]
} Round no. 1
[
  7,
  10,
  1,
  15
] Round no. 1
{
  "array": [
    7,
    1,
    10,
    15
  ]
} Round no. 2
[
  7,
  1,
  10,
  15
] Round no. 2
{
  "array": [
    1,
    7,
    10,
    15
  ]
} Round no. 3
[
  1,
  7,
  10,
  15
] Round no. 3

PS: If you mean you open it in Chrome Console (or something similar) and it looks like this console then it depends on implementation of that console.

The value of both, array and { array } is the position in memory, where the array-values are persisted. These values are changing, so if it did not persist the value of array back in time you logged it, but just the value of the memory segment, then when you expand it, it shows you the current values, not the historical ones.

libik
  • 22,239
  • 9
  • 44
  • 87
  • I'm confused, running the code snippet in the console gives me a different result... – Nico Nov 09 '19 at 17:19
  • @Nico - can you copy-paste what result you have? – libik Nov 09 '19 at 17:27
  • 1
    thanks for explaining that to me, that clears everything up. What I'm trying to do is push the array to a second array ```steps``` after each sorting round but when I check the contents of ```steps``` it shows the same sorted array over and over again. Based on what you pointed out I need to push a copy of the array rather than the reference itself, is that correct? Thanks again – Nico Nov 09 '19 at 17:41
  • 1
    @Nico - exactly, you understand it quite good right now. I recommend to use cloneDeep from lodash package. – libik Nov 09 '19 at 17:44
1

Perhaps a simple example will be clearer:

Enter this in your console:

const arr = [1, 2, 3]; const obj = {arr}; console.log(obj)
DO NOT open the object

Now type:
arr[0] = 11;
...and open the object from the line above. It should read [11, 2, 3] because when you open the object in the console it displays {arr} as it is at that moment, not how it was when it was logged.

Frazer
  • 1,049
  • 1
  • 10
  • 16