1

I was working on displaying the steps to sorting an array and trying to render out the different steps in react. When I call my bubble sort function, the array is already sorted after I click the button.

Creating my state variable:

  const [arr, setArr] = useState(resetArr())

  function resetArr() {
    return new Array(10).fill().map(() => {
      return ({
      num: Math.floor(Math.random() * 100),
      eval: false
    })})
  }

Bubble sort function

  function bubbleSort() {
    const history = [];
    const sArr = arr.slice();
    let len = sArr.length;
    for (let i = len-1; i >= 0; i--) {
      for (let j = 1; j<=i; j++) {
        if (sArr[j-1].num > sArr[j].num) {
          const temp = sArr[j-1].num;
          sArr[j-1].num = sArr[j].num;
          sArr[j].num = temp;
        }
        history.push(sArr);
      }
    }
    console.log(history)
  }

Button and return

  return (
    <div>
      <div className="arr-container">
        {arr.map((item, idx) => 
          <div key={idx} className="arr-item">
            {item.num}
          </div>
        )}
      </div>
      <div>
        <button onClick={() => bubbleSort()}>Bubble</button>
      </div>
    </div>
  )

Console log for history

0: Array(10)
0: {num: 0, eval: false}
1: {num: 3, eval: false}
2: {num: 9, eval: false}
3: {num: 18, eval: false}
4: {num: 33, eval: false}
5: {num: 41, eval: false}
6: {num: 53, eval: false}
7: {num: 65, eval: false}
8: {num: 94, eval: false}
9: {num: 99, eval: false}

1: Array(10)
0: {num: 0, eval: false}
1: {num: 3, eval: false}
2: {num: 9, eval: false}
3: {num: 18, eval: false}
4: {num: 33, eval: false}
5: {num: 41, eval: false}
6: {num: 53, eval: false}
7: {num: 65, eval: false}
8: {num: 94, eval: false}
9: {num: 99, eval: false}

Any help is appreciated, I am completely stuck on why it's working like this.

7
  • Can you post this as a Code Sandbox/ Commented Sep 30, 2020 at 4:45
  • where is the other console.log? the code only shows one after the sorting is done, so I don't see the problem in the output if that's the result of clicking twice Commented Sep 30, 2020 at 4:55
  • @dwjohnston codesandbox.io/s/bubble-sort-39clz Commented Sep 30, 2020 at 4:58
  • @diedu the history is an array that looks somewhat like this, [[{num:0, eval:false},],], I am pushing to history at every stage of the for loop Commented Sep 30, 2020 at 5:03
  • You're pushing the same array to the history array on each loop. Commented Sep 30, 2020 at 5:29

2 Answers 2

1

You need to understand object references in JavaScript and programming languages in general.

As an example:

const array = []; 

const someObject = {
  a: "foo"
};


array.push(someObject); 
someObject.a = "bar"; 
array.push(someObject); 

console.log(JSON.stringify(array, null,2)); 

This doesn't print:

[
  {
    "a": "foo"
  },
  {
    "a": "bar"
  }
]

it prints:

[
  {
    "a": "bar"
  },
  {
    "a": "bar"
  }
]

Because in that first push to the array, you aren't pushing the object as it is at the time, you are pushing a reference to the object.

In this scenario, when you later change the objects a property, (you mutate the object) that value changes in the array.

This kind of confusion is why people like to avoid property reassignment like this, why immutable programming is a thing.

Your code basically has the same problem.

You are pushing the same array to the history array each time it loops, and then you are later mutating that array.

If you change your history.push line to this:

history.push(JSON.parse(JSON.stringify(sArr)));

This solves your problems.

What the parse-stringify does is just clones the array object, ie, it creates a new array object.

Sign up to request clarification or add additional context in comments.

1 Comment

I didn't even think of this... I was so confused, thank @dwjohnston
0

I don't know if this will be helpful at all, but I decided I might as well link it: sandbox!

I thought it would be nice to have the rendering portion implemented so it would be easier to see what is happening to the data.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.