Jackson Quintero
Jackson Quintero

Reputation: 188

How to preserve element position and allow randomization (shuffling) in a JavaScript array?

I don't know if it's the best way I'm implementing it, what I can't do is that pressing the block button only allows randomizing (shuffling) the elements that are not blocked, I tried several ways that doesn't work, for example, when i pressed the locked button, it saved the id and then compare, but i couldn't do it.

    // this array, button locked 
    const dataId = ["b79bc2a0-da09-4620-9b3d-1ed32d697f0a", "a60d0c77-439d-4764-b115-f4c24f857cd1"];

    const data =[
      {
          id: "b79bc2a0-da09-4620-9b3d-1ed32d697f0a"
          name: "three"
          email: "[email protected]"
      },
      {
          id: "c8648167-3103-44f9-b03c-3bd951fb339c"
          name: "two"
          email: "[email protected]"
      },
      {
          id: "a60d0c77-439d-4764-b115-f4c24f857cd1"
          name: "one"
          email: "[email protected]"
      }
    ];

function shuffle(array) {
  let currentIndex = array.length,
    randomIndex;

  // While there remain elements to shuffle.
  while (currentIndex !== 0) {
    // Pick a remaining element.
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;

    // And swap it with the current element.
    [array[currentIndex], array[randomIndex]] = [
      array[randomIndex],
      array[currentIndex]
    ];
  }

  return array;
}

  let locked = [];
    data.filter(
      (d: IList) => !dataId.includes(d.id) && locked.push(d)
    );

    const data = shuffle(locked);

enter image description here

As you can see, what I was doing is not right and I can't think of how to implement it. Is it possible to do something like what I am implementing?

any information you need please let me know

Upvotes: 0

Views: 61

Answers (1)

n--
n--

Reputation: 3856

It can be done by assigning a locked flag to the selected items, create a randomized array with unlocked items, then mapping locked and unlocked items in a resulting array:

const shuffle = array => {
    let r = array.map(i => [i, Math.random()])
        .sort((a, b) => a[1] - b[1]).filter(i => !i[0].locked);
    return array.map(i => i.locked ? i : r.pop()[0]);
};

An example of this in action is below:

label {
  font-family: monospace;
}
<script type="module">

import {State, insert} from '//cdn.jsdelivr.net/npm/karyon/karyon.js';

const data = [
  {
      id: "b79bc2a0-da09-4620-9b3d-1ed32d697f0a",
      name: "three",
      email: "[email protected]"
  },
  {
      id: "c8648167-3103-44f9-b03c-3bd951fb339c",
      name: "two",
      email: "[email protected]"
  },
  {
      id: "a60d0c77-439d-4764-b115-f4c24f857cd1",
      name: "one",
      email: "[email protected]"
  },
  {
      id: "c79bc2a0-da09-4620-9b3d-1ed32d697f0a",
      name: "four",
      email: "[email protected]"
  },
  {
      id: "d8648167-3103-44f9-b03c-3bd951fb339c",
      name: "six",
      email: "[email protected]"
  },
  {
      id: "e60d0c77-439d-4764-b115-f4c24f857cd1",
      name: "nine",
      email: "[email protected]"
  }
];

const shuffle = array => {
    let r = array.map(i => [i, Math.random()])
        .sort((a, b) => a[1] - b[1]).filter(i => !i[0].locked());
    return array.map(i => i.locked() ? i : r.pop()[0]);
};

const rows = State(data.map(({locked = State(), id, email}) => (
    {locked, content: [
      {is: 'input', id, props: {type: 'checkbox', value: locked}},
      {is: 'label', attrs: {for: id}, content: [email, ': ', id]}
    ]}
)));

const app = [
    {is: 'button', content: 'Shuffle',
        listen: {click: () => rows(shuffle(rows()))}},
    {content: rows}
];

insert(app, document.body);

</script>

Upvotes: 1

Related Questions