skip to Main Content

I’m a javascript beginner and I got stuck having a problem. I have a javascript’s function to shuffle the characters in a string in that way that words length and spaces are kept like in original sentence.

function shuffleArray(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}

String.prototype.shuffle = function () {
  // pass to shuffleArray an array of all non-whitespace characters:
  const randomChars = shuffleArray([...this.replace(/s+/g, '')]);
  let index = 0;
  // `S` matches any non-whitespace character:
  return this.replace(/S/g, () => randomChars[index++]);
}

console.log(
  `The keys are under the mat`
  .shuffle()
);

What I want to add is adding to the function a variable with defined letters which should be skipping in shuffle process. Now we have, i.e:

  • original string:

The keys are under the mat

  • now shuffled string looks like:

atd meey eke nTshr hau ert

  • and what I want:
    I want to define characters e.g: [hr] and those letters should stay "frozen" in their positions and not be processed by shuffle function:

final result:

ahd meey ere nTshr ahu ekt

3

Answers


  1. The best solution I can come up with is the following:

    1. Store all the letters you won’t be replacing in an array.
    2. Iterate over the original string, replacing each character with a random character from the array as long as the character you’re replacing isn’t (in your case) either: [‘h’,’r’].

    There’s a lot of ways to go about this, but making it efficient depends on a bunch of factors, such as the specific input string, it’s length and the number of characters in your exclusion array.

    I’d look into using the .split() method, demonstrated here: w3schools .split()

    Hope this helps.

    Login or Signup to reply.
  2. You could take a string of characters who remain and build two regular expression for collection and replacing.

    function shuffleArray(array) {
        for (let i = array.length - 1; i; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [array[i], array[j]] = [array[j], array[i]];
        }
        return array;
    }
    
    String.prototype.shuffle = function (keep = '') {
        keep += '\s';
        const
            chars = this.replace(new RegExp(`[${keep}]`, 'gi'), ''),
            randomChars = shuffleArray([...chars]);
       
        let index = 0;
        return this.replace(new RegExp(`[^${keep}]`, 'gi'), () => randomChars[index++]);
    };
    
    console.log('The keys are under the mat');
    console.log('The keys are under the mat'.shuffle());
    console.log('The keys are under the mat'.shuffle('hr'));
    Login or Signup to reply.
  3. I believe this code does what you are looking for:

    function shuffleString(string, fixed) {
        let result = '';
        const allChars = Array.from(string);
        const fixedChars = Array.from(fixed); 
        fixedChars.push(" "); // Consider the blank space as a fixed character, as you wish to maintain the separation on the string
        const singleChars = Array.from(string).filter(char => !fixedChars.includes(char));
    
        allChars.forEach((char) => { 
            if (fixedChars.includes(char)) { // If the sting is fixed, just add it
                result += char;
            } else { // If string is not fixed, get a random one
                const randomPosition = Math.floor(Math.random() * (singleChars.length));
                result += singleChars[randomPosition];
                singleChars.splice(randomPosition, 1); // Remove from the options array, since it should not be selected more than once
            }
        });
        
        return result;
    }
    
    console.log(shuffleString('this is a test', 'et'));

    It is O(n), n being the number of letters in the text.
    Hope it helps!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search