How to do Nested For Loops in Functional Style

I'm in the process of learning functional programming, and completely getting rid of for loops has been a challenge sometimes, because they provide so much control and freedom. Below is an example of checking if a string is an isogram or not (no letters should be repeated). With nested for loops, it became an easy solution. Is there a way to do this the functional way with any high order functions or anything else? Any suggestion would be a huge help.

Code:

function isIsogram(string) {
  let array = string.split('');
  let condition = true;
  for (let i = 0; i < string.length; i++) { //first loop picks character
    for (j = i + 1; j < string.length; j++) { //second loop compares it rest
      if (array[i].toLowerCase() == array[j].toLowerCase())
        condition = false; //if repeat, the condition false
    }
    return condition;
  }
}

Answers:

Answer

You can use every or some together with a suitable string function:

function isIsogram(string) {
    string = string.toLowerCase(); // case insensitive
    return string.split('').every(function(character, index) {
        return !string.includes(character, index+1);
    });
}

Instead of includes you might also have utilised indexOf.

Answer

You can sort the String first and then apply every on it. It will stop the iteration as soon as two successive letters are the same:

Here is an improved implementation. Credit goes to @Xotic750:

function isIsogram(x) {
  return Array.from(x.toLowerCase()).sort().every((y, i, xs) => i === 0 
   ? true
   : y !== xs[i - 1]);
}

console.log( isIsogram("consumptively") );
console.log( isIsogram("javascript") );

The implementation uses Array.prototype.every's second parameter, which represents the index of the current element (of the iteration). Please note that isIsogram solely depends on functions and their arguments.

Answer

Another example, like @Bergi but using some ES6 features for comparison.

function isIsogram(string) {
  string = string.toLowerCase(); // case insensitive
  for (let character of Array.from(string).entries()) {
    if (string.includes(character[1], character[0] + 1)) {
      return false;
    }
  }
  return true;
}

console.log(isIsogram('abc'));
console.log(isIsogram('abca'));

How your ES3 style code could have looked (noting some of the issues pointed out in the comments)

function isIsogram(string) {
  string = string.toLowerCase(); // case insensitive
  var length = string.length;
  for (var i = 0; i < length; i += 1) {
    for (var j = i + 1; j < length; j += 1) {
      if (string.charAt(i) === string.charAt(j)) {
        return false;
      }
    }
  }
  return true;
}

console.log(isIsogram('abc'));
console.log(isIsogram('abca'));

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.