Sorting Visualizer - Why won't my highlights update when one of my swapped out bars is the next in line to get swapped in?
I'm creating a sorting visualizer, and it's implemented by using synchronous sorting algorithms that push animations to a queue to be handled in the async function animateArrayUpdate
. The purpose of the highlights is to indicate the bar which is next up to get sorted. In the case of selection sort, this would be the bar at minIndex which will be swapped with the bar at the current index or i
on the next iteration of the loop. The sorting/swapping works perfectly, and the highlighting mostly works, except when the following scenario occurs: The bar at i
gets swapped out for a bar at minIndex and then is next up to get swapped in for the next i
. In these cases, the bar that got swapped in the last iteration retains its highlight for that iteration so the newly swapped-in bar never gets highlighted. I'll show a trivial example with a mostly sorted array, but the extent to which the rest of the array is sorted is irrelevant, and this wonky highlighting behavior will happen any time the above conditions are met.
Here, the second bar is highlighted to show that it's the minimum index of this iteration and will get swapped in next.
Here is what happens after the swap. As you can see, the first bar retains its highlight. What needs to happen is that the first bar should lose its highlight and the second bar should become highlighted (but not swapped with anything since it's already in place) because it's the new minIndex. This is in fact what happens in all cases where a freshly swapped bar is not immediately up to get swapped again on the very next iteration, i.e., in the vast majority of cases.
const selectionSort = (arr) => {
const animations = [];
const copy = [...arr];
for (let i = 0; i < copy.length - 1; i++) {
let minIdx = i;
for (let j = i + 1; j < copy.length; j++) {
if (copy[j].correctPos < copy[minIdx].correctPos) {
minIdx = j;
}
}
animations.push({
action: "color",
arr: [...copy],
highlightedIndex: minIdx,
swap1: i,
swap2: minIdx,
});
swapBarsMutable(copy, i, minIdx);
animations.push({
action: "move",
arr: [...copy],
highlightedIndex: minIdx,
swap1: i,
swap2: minIdx,
});
}
return animations;
};
const animateArrayUpdate = async (animations) => {
for (let i = 0; i < animations.length; i++) {
const anim = animations[i];
const bars = barsContainer.current.children;
let highlightedBar = bars[anim.highlightedIndex];
if (anim.action === "color") {
highlightedBar.classList.add(barStyles["bar-highlighted"]);
await new Promise((resolve) => {
timers.current.push(setTimeout(resolve, 2000));
});
}
highlightedBar.classList.remove(barStyles["bar-highlighted"]);
if (anim.action === "move") {
setBarsToRender(swapLefts(anim.arr, anim.swap1, anim.swap2));
}
}
setIsPlaying(false);
};
Here is the code. I can provide a sandbox example if the problem isn't apparent from just this fragment. Basically, the bars get rendered by a dumb component that iterates over the barsToRender stateful array. Then, the following line gets passed into the play button component and gets called onClick. Again, the general structure of the program seems to have no issues, and the highlighting problem seems pretty local. Thanks for the help!
algorithmToPlay = () => { animateArrayUpdate(selectionSort(barsToRender)); };
Edit: I was debugging and played the first two animations only, and it does appear that the highlight is removed after the swap. However, it is reapplied to the wrong bar. Furthermore, on the third animation (which is the problematic one), the highlightedIndex is correctly assigned with the value of 1. But this seems to be pointing to the bar which is now at 0 for some reason.
Via Active questions tagged javascript - Stack Overflow https://ift.tt/JfaeVyQ
Comments
Post a Comment