Can someone check this code and tell me if there is a less convoluted way to do this?

Hello all.

I just finished the codeCademy “Practice JavaScript Syntax: Arrays, Loops, Objects, Iterators”
informational. At the bottom of the informational, there are some code challenges. One of those challenges is as follows:

Write a function subLength() that takes 2 parameters, a string and a single character. The function should search the string for the two occurrences of the character and return the length between them including the 2 characters. If there are less than 2 or more than 2 occurrences of the character the function should return 0.

This is the code I came up with after what I feel like was a ridiculously long effort…

const subLength = (strings, s) => { let count = 0 let position = strings.indexOf(s); while (position !== -1) { count++; position = strings.indexOf(s, position + 1); }; if (count !== 2) { return 0; } else { let stringArr1 = strings.slice(strings.indexOf(s)); let stringArr2 = stringArr1.slice(0, stringArr1.lastIndexOf(s) + 1); /*the purpose of these variables is to end up with a string that only contains the characters between and including the repeated characters (i.e. funny in stringArr1 would become nny, and then in stringArr2 would become nn. That way, stringArr2.length will return a value that is equal to the space between the repeated letters (including the letters)*/ return stringArr2.length; } } console.log(subLength('springs', 's')); //output is 7 console.log(subLength('funny', 'n')); //output is 2 console.log(subLength('assets', 's')); //output is 0 console.log(subLength('frank', 'f')); //output is 0

When I checked this code in codeCademy, it passed the test. In execution, it DOES produce the desired effect, but I feel like this code is so complicated for the seemingly simple task. If there is a simpler solution that I am just too dumb at the moment to figure out, could someone please point it out to me?

I’d like to start by saying that no solution is a dumb one when you’re still learning. Even in production projects you still see inefficient code because when working to deadlines, working is more important than quick in the first instance. I think your solution is nice, makes good use of loops and string methods to accomplish what needs to be accomplished.

However if you want to see another way of doing it I can give you mine. I like this solution because it’s short, easy to read (in my opinion) and pretty clean. Here it is below.

const subLength = (string, letter) => {
  // Escape clause if not 2 instances
  if (string.split(letter).length - 1 != 2) return 0
  // Find first instance
  let position1 = string.indexOf(letter);
  // Find second instance
  let position2 = string.indexOf(letter, position1+1) + 1
  return position2 - position1
}

console.log(subLength('springs', 's'));  //output is 7
console.log(subLength('funny', 'n')); //output is 2
console.log(subLength('assets', 's')); //output is 0
console.log(subLength('frank', 'f')); //output is 0

What this does is first checks if the string has exactly 2 instances of the desired letter. It does this by splitting the string into an array on that letter, which will always give you an array with n+1 elements, where n is the number of instances of the divider. Therefore taking the length of that array-1 will give us n, and if this is not equal to 2 then the function instantly returns 0, meaning there’s no other code run if the conditions aren’t met. These types of escape clauses are personal preference, but I really like them as you have a clean, clear way to remove all undesired inputs, meaning that the function body is only run in the use case you want.

The next main part is getting position2 as position1 is clear in it’s function. the indexOf() string method can take a second argument that tells it where in the string to start searching from, in this case we choose the element after the first instance. In this case since there’s only ever 2 instances of a letter this is functionally equivalent to lastIndexOf() however if more than 2 instances were allowed this method could be the only one that works if you wanted the length between the first and the second instances. Then since strings are zero-indexed you need to add an extra 1 at the end to account for the inclusion of the last character.

Then it’s just simply a case of subtracting position1 from position2, as position1’s index is already inclusive of itself, and this gives us our final answers desired as shown at the end of this post.

The last thing to mention is your feeling that your code is complicated for a simple task. The answer is surprisingly that actually working with strings can be far from simple. “Just find the length between two letters” is easy on paper but can be a little complex in code just because of the rigid rules required to actually make the function work for all types of string. However I think it’s a good impulse to always be thinking there could be better ways to write your code, and it’ll lead to you having a strong understanding of all the concepts in the language, since you’ll need to to identify weaknesses in your code.

const subLength = (string, letter) => { // Escape clause if not 2 instances if (string.split(letter).length - 1 != 2) return 0 // Find first instance let position1 = string.indexOf(letter); // Find second instance let position2 = string.indexOf(letter, position1+1) + 1 return position2 - position1 } console.log(subLength('springs', 's')); //output is 7 console.log(subLength('funny', 'n')); //output is 2 console.log(subLength('assets', 's')); //output is 0 console.log(subLength('frank', 'f')); //output is 0
2 Likes

This is an awesome reply. Thank you for your encouraging words at the start and finish of your reply. You are right, and I am pleased that I was able to get the code working. HTML and CSS were so much easier for me to understand and implement than JS, so I am pleased anytime I am able to figure out the solution. I do like how clean and concise your code is, and I appreciate your detailed explanation as to what everything does.

2 Likes