Reverse Vowels of a String The task

is taken from leetcode


  Write a function that takes a string as input and reverse only the
  vowels of a string.
  
  Example 1:
  
  Input: "hello"
  
  Output: "holle"
  
  Example 2:
  
  Input: "leetcode"
  
  Output: "leotcede"
  
  Note: The vowels does not include the letter "y".


My first solution

/**
 * @param {string} s
 * @return {string}
 */
var reverseVowels = function(s) {
  const LEN = s.length;
  const str = [...s];
  const vowels = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'];
  const rev = [];
  for (let i = 0; i &lt; LEN; i++) {
    if (vowels.includes(s[i])) { rev.push(s[i]); }
  }
  for (let i = 0; i &lt; LEN; i++) {
    if (vowels.includes(str[i])) { str[i] = rev.pop(); }
  }
  return str.join('');
};


My second solution

/**
 * @param {string} s
 * @return {string}
 */
var reverseVowels = function(s) {
  if (s.length &lt;= 1) { return s; }
  const sForward = [...s];
  const sBackward = [...s].reverse();
  const LEN = s.length - 1;
  let left = -1, right = -1;
  const VOWELS = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'];
  const findVowel = start =&gt; (x, i) =&gt; start &lt; i  &amp;&amp; VOWELS.includes(x);
  while(true) {
    left = sForward.findIndex(findVowel(left));    
    right = sBackward.findIndex(findVowel(right));
    if (left &gt;= LEN - right || left === -1 || right === -1) { return sForward.join(''); }

    [sForward[left], sForward[LEN - right]] = [sBackward[right], sForward[left]];
  }
  return sForward.join('');
};


My third solution

/**
 * @param {string} s
 * @return {string}
 */
var reverseVowels = function(s) {
  if (s.length &lt;= 1) { return s; }
  const str = [...s];
  let left = 0;
  let right = s.length - 1;
  const VOWELS = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'];
  while(left &lt; right) {
    if (VOWELS.includes(str[left]) &amp;&amp; VOWELS.includes(str[right])) {
      [str[right], str[left]] = [str[left], str[right]];      
      left++;
      right--;
    } else if (VOWELS.includes(str[left])) {
      right--;
    } else {
      left++;
    }
  }
  return str.join('');
};


My fourth solution

/**
 * @param {string} s
 * @return {string}
 */
var reverseVowels = function(s) {
  if (s.length &lt;= 1) { return s; }
  const str = [...s];
  let left = 0;
  let right = s.length - 1;
  const map = new Map();
  map.set('a', true);
  map.set('e', true);
  map.set('i', true);
  map.set('o', true);
  map.set('u', true);
  map.set('A', true);
  map.set('E', true);
  map.set('I', true);
  map.set('O', true);
  map.set('U', true);
  while(left &lt; right) {
    if (map.get(str[left]) &amp;&amp; map.get(str[right])) {
      [str[right], str[left]] = [str[left], str[right]];      
      left++;
      right--;
    } else if (map.get(str[left])) {
      right--;
    } else {
      left++;
    }
  }
  return str.join('');
};


My fifth solution

/**
 * @param {string} s
 * @return {string}
 */
var reverseVowels = function(s) {
  if (s.length &lt;= 1) { return s; }
  const str = [...s];
  let left = 0;
  let right = s.length - 1;
  const set = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']);

  while(left &lt; right) {
    if (set.has(str[left]) &amp;&amp; set.has(str[right])) {
      [str[right], str[left]] = [str[left], str[right]];      
      left++;
      right--;
    } else if (set.has(str[left])) {
      right--;
    } else {
      left++;
    }
  }
  return str.join('');
};
I recommend using the Array.prototype methods. 

These lend themselves to adopting a functional style of programming.

Functional programming is a lot easier to test, as a pure function always returns the same result and never mutate objects. 



const vowels = ['a','e','i','o','u']; 
function vowelStringReverse(str) {
  
    //split the string into an array of chars, that includes their index position
    const strArray = str.split('').map((v,i) =&gt; ({
        value: v, 
        i: i, 
        isVowel: vowels.includes(v)
    })); 
    
    //For just the vowels, 
    //Create index position lookup, where the index positions are reversed
    const vowelsReverseIndexLookup = strArray.filter(v =&gt; v.isVowel)
    .reduce((acc, cur, i, array) =&gt; {
        return {
            ...acc, 
            [array[array.length-1-i].i]: cur.value
        }; 
    
    }, {}); 
    
    //Now iterate through the string, and look up the vowel from the lookup. 
    const strReversed = strArray.map((v,i) =&gt; {
        if (v.isVowel) {
            return vowelsReverseIndexLookup[i]
        }
        else {
            return v.value; 
        }
    }); 
    
    return strReversed.join(''); 
    
}


console.log(vowelStringReverse('hello')); 
console.log(vowelStringReverse('leetcode')); 




In this example I've given, if you wanted, you could then pull out the anonymous functions I've declared, and write tests for them: 

for example: 

const vowelsReverseIndexLookup = strArray.filter(v =&gt; v.isVowel)
.reduce(reverseIndexReducer, {}); 

//elsewhere: 

const reverseIndexReducer = (acc, cur, i, array) =&gt; {
    return {
        ...acc, 
        [array[array.length-1-i].i]: cur.value
    }; 

};