Few issues with search and replace

Hi I’m having some problems with this code. Please let me know first if my comments and method of doing this is correct, then if my regex is correct to check if first letter of before is lowercase.

I’m getting -1 for caseChecker but if regex is correct it should be 1. If my approach and regex are correct, then please let me know if it’s the return that is not working as well.

Thanks

  **Your code so far**

function myReplace(str, before, after) {
// create regex to check if first letter is lowercase 
let lowerCase = before.match(/^[^a-z]*$/);
// get index of lowercase letter 
let caseChecker = before.indexOf(lowerCase);
console.log(caseChecker);
// if index 0 of before is lowerCase replace lower case else return with upper case
if (caseChecker > 0) {
  return str
    .replace(before, after)
    .after.toLowerCase()
} return str
    .replace(before, after)
    .after.charAt(0).toUpperCase()
}  

// case checker returning -1 when it should return 1
// Cannot read property 'toUpperCase' of undefined

console.log(myReplace("I think we should look up there", "up", "Down"));
// I think we should look down there


  **Your browser information:**

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36.

Challenge: Search and Replace

Link to the challenge:

The first issue I see is this:

return str
      .replace(before, after)
      .after.charAt(0).toUpperCase()

Does the method replace return an object with the property “after”?

I’m not sure why you are doing this:

  // create regex to check if first letter is lowercase 
  let lowerCase = before.match(/^[^a-z]*$/);
  // get index of lowercase letter 
  let caseChecker = before.indexOf(lowerCase);

The instructions say:

Note: Preserve the case of the first character in the original word when you are replacing it. For example if you mean to replace the word Book with the word dog , it should be replaced as Dog

So, don’t we only care about the casing of the first letter? I would expect to test the casing of the first character of before.

I thought this would replace before with after, which seems to be working. Just not the right case. I’m not so sure what you mean by property I thought it’d work as callback (sorry again maybe I’m not understanding the verbiage)

Sadly I’m lost with regex and still trying to learn. I thought what I wrote would check if there is an index of 0 where before is lowercase or not

I thought this would replace before with after, which seems to be working.

JavaScript disagrees:

Uncaught TypeError: Cannot read property 'charAt' of undefined
    at myReplace

Sadly I’m lost with regex …

Yeah, regex is weird. A lot of people struggle with it. But it’s also very powerful.

OK, maybe I see what you are trying to do there. I guess part of my confusion is the variable naming.

So you have this regex: /^[^a-z]*$/

As I read that, you are asking it to match a string that starts with a char that is not lowercase and can have any number of non-lowercase chars, all the way to the end. In other words, the string will only match if it has no lowercase anywhere in it. That is not what we want.

I think this should be simplified. Rather than check if the first char is not lowercase, why not check if it is uppercase. Avoid negative logic when you can. You also don’t care about whether or not any char after the first is uppercase and you don’t care how many there are. To me, that regex should have six characters (ignoring /) - you can get rid of most of the end of what you have.

And you if you have the right regex, you don’t need to do the indexOf check - you just need to see if there is a match.

OK, next, what does “caseChecker” do? What do the values mean? You should be able to tell from the variable name. I would expect you to do the test to see if it is in fact uppercase here and store it in a variable like “isFirstCharUppercase” - that tells me exactly what that variable means. You do that logic on the same line as the match.

1 Like

See what you can come up with and check back if you run into trouble.

Yeah I’m just googling and looking at the cheatsheet as much as I can. Wouldn’t the right regex be /^A-Z/ to check if it starts with A-Z in upper case?
^ = first index
A-Z = all uppercase letters
I’m testing this out but getting null even when I switch it to capital U in up, so it’s probably not right.

My new approach taking what you said would be to use this

function myReplace(str, before, after) {
  // create regex to check if first letter is uppercase 
  let isThisUpperCase = before.match(/^A-Z/);
  console.log(isThisUpperCase);  
  
  // if before does not start with uppercase replace lower case else return with upper case
  if (isThisUpperCase == null) {
    return str
       .replace(before, after.toLowerCase());
  } return str
      .replace(before, after)//.charAt(0).toUpperCase())
 }  

console.log(myReplace("I think we should look up there", "up", "Down"));
// I think we should look down there

I’m sure I still have a lot of issues here though. I’m just trying onne at a time

no, that would match literally a string that starts with "A-Z", you want to use a character class instead ([])

So just this instead? (/^[A-Z]/)

My code so far is

function myReplace(str, before, after) {
  // create regex to check if first letter is uppercase 
  let ifUpperCase = before.match(/^[A-Z]/);
  
  // if before does not start with uppercase replace lower case else return with upper case
  if (ifUpperCase == null) {
    return str
      .replace(before, after.toLowerCase());
  } return str
      .replace(before, after.charAt(0).toUpperCase())
 }  

console.log(myReplace("I think we should look up there", "up", "Down"));
// I think we should look down there

Hoping .replace(before, after.charAt(0).toUpperCase()) is my only issue now

So, firstly, enclose any single char with multiple possible matches in [] like this:
/^[A-Z]/ this matches the first char in the string if it is capitalized. What you have is matching the literal string of A-Z at the beginning of before.

Second, RegExp.prototype.test() that returns boolean seems more appropriate instead of match.

Third, as it currently stands, the second .replace in your code would swap the matched before with only the first char of after.

Isn’t this what I included in my last comment? Doesn’t [A-Z] mean any character between a to z in the alphabet?

What makes this more appropriate? Would match not work? Asking because I’m dealing with multiple issues and don’t want to change things unless it wont work without it

Yeah but even when i ignore the condition to capitalize and just check if the regular replace is working by capitalizing U in “up” (before), it doesn’t work at all and doesn’t do any replacing

Any updates? This is my code and it appears the last replace is the only thing not working.

function myReplace(str, before, after) {
  // create regex to check if first letter is uppercase 
  let ifUpperCase = before.match(/^[A-Z]/);
    // if it is not uppercase replace with lower case "after" else return with upper case "after"
  if (ifUpperCase == null) {
    return str
      .replace(before, after.toLowerCase());
  } return str
      .replace(before, after)
      // this replace is not working at all and then if I get it to work I need 
      // to figure out how to make it upper case first letter. 
      // Have tried using toUpperCase and charAt but not getting it to work right.   
      
 }  

console.log(myReplace("I think we should look up there", "Up", "Down"));
// I think we should look down there

This is very close. The issue is that if before starts with an uppercase, what are you going to do in your second return. You need to make sure that whatever you are using for after also starts with an uppercase.

When I fix that, the code passes for me.

1 Like

Sorry for the late reply.

  1. When I replied I did not see you’ve already fixed the regex with []. Apologies.

  2. .test() IMO is more appropriate because it test for regex match in target string, and returns true if there is any match, false if there isn’t. While .match() returns a string/array depending on regex which then you have to further test. But both do work so it’s not very relevant to the code.

  3. I don’t know if I worded my suggestion correctly, but what I meant was your code at that point in time was doing this:

If before is a capitalized word, then capitalize the first letter of after, and remove the rest of the word.

So you would have words like “down” become “D”.

I have just read your most recent code. This is about string manipulation which I believe was covered in the basic JS stuff, key points are:

  1. strings are immutable in JS (you can’t change characters in a string, only reassign)
  2. you can access chars in a string with str.charAt(i) or str[i] with i being the index of the char
  3. you can access substrings in a string with .slice() or .substr()
  4. you can use .toUpperCase() and toLowerCase() on chars and strings
  5. you can combine strings on the fly using +

If you are still having trouble, see following example:

const str1="hyperventilate";
const str2=str1.charAt(0).toUpperCase(); //str2 = "H"
const str3=str1.slice(1); //str3="yperventilate"
const str4=str2+str3; //str4="Hyperventilate"
1 Like

Thank you so much. I feel this should work but it’s not. I don’t believe the second replace is working at all

return str
      .replace(before, after[0].toUpperCase() + after.slice(1));
 }

actually when I sub this line of code back into your last updated function, it passes. Can I see the entirety of your code again please?

Definitely

function myReplace(str, before, after) {
  let ifUpperCase = before.match(/^[A-Z]/);
  if (ifUpperCase == null) {
    return str
      .replace(before, after.toLowerCase());
  } return str
      .replace(before, after[0].toUpperCase() + after.slice(1));
 }  

console.log(myReplace("I think we should look up there", "Up", "Down"));

*update weird I just saw that it passes the test but the code I sent over doesn’t return “I think we should look Down there”

Read the note about preserving the case again. The function call you have would not replace “Up” with “Down” as “Up” (capital U) doesn’t exist in the original string.

console.log(myReplace("I think we should look up there", "Up", "Down")); // I think we should look up there

console.log(myReplace("I think we should look Up there", "Up", "Down")) // I think we should look Down there
1 Like

that’s because we are not meant to be case insensitive when looking for the before string in str. so in this specific case of Up and Down, your function looks for case sensitive Up and does not find one, therefore it returns the original string as is.

Your code is functioning as intended. Good Job!

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.