Skip to content

Instantly share code, notes, and snippets.

@diraneyya
Last active October 18, 2022 23:21
Show Gist options
  • Save diraneyya/b648e03dfddd764f51f8f141b27c2949 to your computer and use it in GitHub Desktop.
Save diraneyya/b648e03dfddd764f51f8f141b27c2949 to your computer and use it in GitHub Desktop.

CREATIVE SOLUTIONS FOR FIRST NON-REPEATING CHARACTER DOJO

DOJO Links:

Solution by Manisha/Sveta, modified for case-insensitive test cases

checks if a character is non-repeating by looking for the 2nd match in a string and ensuring that this 2nd match exists. Based on String.prototype.indexOf (check the second usage in the Syntax section on MDN).

const firstNonRepeatingLetter = function (string) {
  const stringLower = string.toLowerCase();
  for (var i = 0; i < string.length; i++)
    if (stringLower.indexOf(stringLower[i], stringLower.indexOf(stringLower[i]) + 1) == -1)
      return string[i];

  return '';
}

Solution by Alex, modified for case-insensitive test cases

Solution is based on creating a new string newStr with the non-repeating characters only, then returning the first character from such string if it exsts, otherwise return an empty string.
This solution uses two nested for loops and is based on String.prototype.replace to delete repeated characters from a string.

const firstNonRepeatingLetter = function (str) {
  let newStr = str;
  
  for (let i = 0; i < str.length; i++)
    for (let j = 0; j < str.length; j++)
      if (i === j)
        continue;
      else if (str[i].toUpperCase() === str[j].toUpperCase())
        newStr = newStr.replace(`${str[i]}`, '');
  
  return newStr.length > 0 ? newStr[0] : '';
}

Solutions by Arkadii

These solutions are all based on the Array.prototype.reduce method and incorporate an array of smart ideas and tricks related to mutating the array during a reduce, or using a right reduce instead of a standard (i.e. left) reduce. In one of the variants, an exception is used to escape a standard (i.e. left) reduce. All of these solutions use the formula text.indexOf(letter) === text.lastIndexOf(letter) to detect a non-repeating character (i.e. letter) in a string (i.e. text), which utilizes the two methods: String.prototype.indexOf and String.prototype.lastIndexOf

// Uses exceptions to escape a reduce
const firstNonRepeatingLetter = function (param) {
    try {
        param.split('')
            .reduce((a, e) => {
                if (param.indexOf(e) === param.lastIndexOf(e)) throw e; 
            }, '')
  } catch (solution) {
    return solution
  }

  return ''
}
// Does not work for case insensitive test cases
const firstNonRepeatingLetter = (param) =>
  param.split('')
    .reduceRight((a, e) => 
        (param.indexOf(e) === param.lastIndexOf(e) ? e : a)
    , '')
// Modified for case insensitive test cases
const firstNonRepeatingLetter = (param) =>
  param.split('')
    .reduceRight((a, e) => 
        ([...param.matchAll(RegExp(e, 'gi'))].length === 1 ? e : a)
    , '');
// Modified for case insensitive test cases
const firstNonRepeatingLetter = (param) =>
  param.split('')
    .reduceRight((a, e1) => 
        ( param.split('').filter( e2 => e1.toLowerCase() === e2.toLowerCase() )).length === 1 ? e1 : a
    , '');
// Modified for case insensitive test cases
const firstNonRepeatingLetter = (param) =>
  param.split('')
    .reduceRight((a, e1) => 
        ( param.split('')
            .filter( e2 => e1.toLowerCase() === e2.toLowerCase() )
        ).length === 1 ? e1 : a
    , '');
// Mutate array during reduce, does not work in case insensitive test cases
const firstNonRepeatingLetter = (param) => 
    (arr = param.split(''))
        .reduce((a, e) => 
            (param.indexOf(e) === param.lastIndexOf(e) ? (e + ((arr.length = 0) || '')) : a)
        , '')
// Mutate array during reduce, works for case insensitive test cases
const firstNonRepeatingLetter = (param) => 
    (arr = (paramLower = param.toLowerCase())
        .split(''))
        .reduce((a, e, i) => 
            (paramLower.indexOf(e) === paramLower.lastIndexOf(e) ? 
                (param[i] + ((arr.length = 0) || '')) : a)
        , '');

Solution by Orwa

This solution is based on the Set()constructor in Javascript, the Array.prototype.find method, case-insensitive regular expressions, and the String.prototype.matchAll method. It is a neat solution and highly readable.

const firstNonRepeatingLetter = text =>
    [...new Set(text.split(''))]
        .find(letter => [...text.matchAll(RegExp(letter, 'gi'))].length === 1)
// Improved
const firstNonRepeatingLetter = text =>
    [...new Set(text.split(''))]
        .find(letter => text.match(RegExp(letter, 'gi')).length === 1) || ''
// Simplified
const firstNonRepeatingLetter = text =>
    text.split('').find(letter => text.match(RegExp(letter, 'gi')).length === 1) || ''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment