I created my own way to search my name, but anyway to make it not case sensitive?


#1



The code functions properly and even searches for ONLY my name and no other similar strings. It also has a counter for how many times it was found. I only really have two questions:

  1. Have I done anything inefficiently here? I'm excited that I was able to create my own version of the code and have it work properly but being a new coder, I'm sure I could have done something slightly more efficiently somewhere. I understand that in coding you not only want to reach your goal but do so with the simplest and most efficient code.

  2. Anyway to make matching strings NOT case sensitive? If I have "shaun" somewhere in the string, it won't match with "Shaun".


var text = "Shane Shawn Seany ShaunsdswfBlasgsdgtweyewyShaunsfgwetewtye Shaungfasgasgasdgy ShanesdfsafrShaun Shaun Shanesdgseygeyy Shaun Shawn Shann";
var myName = "Shaun";
var hits = [];
var counter = 0;
var i, x, y, a;
var temp1;
var totalFound = 0;

for(i=0; i < text.length; i++) { 
    if(text[i] === "S") {
        for(x=i, y=0; x < i+myName.length; x++, y++) {
            if(text[x] === myName[y]) {
                counter++;
                if(counter === myName.length) {
                    for(a=x-(myName.length-1); a <= x; a++) {
                        hits.push(text[a]);
                    }
                    counter = 0;
                    totalFound++;
                }
            } else {
                counter = 0;
            }
        }
    }
}

if(hits === 0) {
    console.log("Your name was not found.");
} else {
    console.log(hits);
    console.log("Your name has been found" + " " + totalFound +" times.");
}


#2

1) WIll get back to you after shower, but at a glance, three loops looks like one too many
2) Instead of testing if the two characters are equal, you would test if they are equal after normalising them (converting to all upper or all lower)


#3

Right, the third loop is for copying the text. Fair enough, since with a case-insensitive search they may actually differ.
Might wanna create a string with the full name instead of adding each charater individually.

Those lines should all be removed, they lack purpose or should be created in the loop. Number of hits can be determined by checking the length of the hits, and "counter" which is used to determine whether at the end of a name is something you can look at the loop variable for instead

A position in the string can be described with one integer, yet you have two.

"S" can be found in the myName variable, don't repeat it here


After fixing all that stuff the code will look fairly different, should be easier to reason about it and look for any other problems if there are any others - no point trying to analyse it any more before having cleaned this up


#4

First loop is looking through each string for the first "S".

Second loop is for going through the next 4 strings after it finds the first "S" to verify that they ALL match(since I don't want to start adding them to hits[] before knowing if all strings match after the first letter rather than only some) before moving onto the third loop which incrementally pushes each string to hit[].

Third loop only happens after all the strings are verified as matching to myName and begins to push those strings to hit[].

Perhaps I could have used less for loops but if I can it's flying over my head at the moment, lol.


#5

I have two because x will be the position in which the first number is found in the text array, and y must start at 0 so it can be incrementally compared to the array position starting at 0 from myName(the S's position). In other words, if I only used one variable here, and I tried to compare each loop cycle like: (if text[x] === myName[x]) it wouldn't work, because x wouldn't be a valid position in myName. With both variables, I start x wherever the next "S" was found, and start y at 0(position for "S" in myName) and have them both increment up each cycle to allow comparing properly.

I figured as much. I was still learning scope a bit and I just made them all global so I didn't have to worry about anything messing up in case I used the wrong scope before I fully understood them.

Also, I do need that counter there because checking the other variables will not work, as they will increment whether text[x] === myName[y] is true or not. I need it to increment only when they match, so I know when all letters match rather than only some. Maybe I'm not understanding what you mean, though.


#6

You can have an offset starting from zero, and add the position from the outer loop to it to obtain the position of the character

You don't. When the offset is at the last character (length-1) then you're able to tell that it's the last iteration


#7

The counter isn't to let me know that I'm at the last iteration, though, it's to let me know that all characters matched within all possible iterations.


#8

That happens at the last iteration.

But you would also need break to exit as soon as a non-match is found

Alternatively create a bool before starting that loop, set it to false if a non-match is found and then check that after the loop


#9

It can get to the last iteration without all characters matching, so I'm not seeing what you're saying here. The for loop can finish looping without every character matching, in which case I want nothing to happen.


#10

Yeah, so you would need a break to abort the loop so that it only gets to the last iteration (after checking the last char as well) if all match

for (var i = 0; i < 10; ++i) {
    console.log(i);
    if (i == 3) {
        break;
    }
}

output:

0
1
2
3

And like mentioned, a boolean is fine too, both that and break will result in simpler code than what you do with counter.

break also means less operations carried out since it stops looking where there clearly isn't a match. But it's barely worth mentioning when the string being searched for is a name and not something that could get really long


#11

So something like? (Tested and works as well!):

(edited for formatting // ionatan)

for(i=0; i < text.length; i++) { 
    if(text[i] === "S") {
        for(x=i, y=0; x < i+myName.length; x++, y++) {
            if(text[x] === myName[y]) {
                if(x === (i+myName.length)-1) {
                    for(a=x-(myName.length-1); a <= x; a++) {
                        hits.push(text[a]);
                    }
                    totalFound++;
                }
            } else {
                break;
            }
        }
    }
}

#12

Is also something that's already being done at



That's really far from the condition, change the condition so it's the condition for aborting instead

if chars don't match
    abort search
if last iteration
    all match, so register result


still got this:


and this

(check first letter of myName instead)


#13

/*jshint multistr:true */
var text = "Shane Shawn Seany ShaunsdswfBlasgsdgtweyewyShaunsfgwetewtye Shaungfasgasgasdgy ShanesdfsafrShaun Shaun Shanesdgseygeyy Shaun Shawn Shann";
var myName = "Shaun";
var hits = [];
var counter = 0;
var i, x, y, a;
var temp1;
var totalFound = 0;

for(i=0; i < text.length; i++) { 
        for(x=i, y=0; x < i+myName.length; x++, y++) {
            if(text[x] !== myName[y]) {
                break;
            }
            if(x === (i+myName.length)-1) {
                totalFound++;
                for(a=x-(myName.length-1); a <= x; a++) {
                hits.push(text[a]);
                }
            }
        } 
}

if(hits === 0) {
    console.log("Your name was not found.");
} else {
    console.log(hits);
    console.log("Your name has been found" + " " + totalFound +" times.");
}

It's 1:30AM here so I've got the sleepy brain. I changed up the part that had counter and removed the double checking of the first letter. I'll look into fixing the "double variable" in my second for loop; I honestly didn't quite get what you were saying(not sure how I'd compare the correct position of myName when i and x will be out of range to compare with) but I'm sure I'll get it tomorrow. Mainly I don't understand when you say I can "have an offset starting from 0". What do you mean by offset?


#14

If the first index is START, then the first character is at START+0, the second is at START+1 and so on.

If you know where it starts and that you want the seventh character, then you would add 6 to the starting position

If there are two start positions, then you can use one variable to keep track of the amount of steps from the starts to compare


#15

for(i=0; i < text.length; i++) {
for(x=0; x < myName.length; x++) {
    if(myText[i+x] === myName[x]);

Something sorta like that?

EDIT: Here's what I got this morning after your suggested changes. Thanks a lot, I learned a lot from them! Can't help but admit it's slightly discouraging though after realizing how many mistakes went over my head.

var text = "Shane Shawn SShauneany ShaunsdswfBlasgsdgtweyewyShaunsfgwetewtye Shaungfasgasgasdgy ShaneShaunsdfsafrShaun Shaun Shanesdgseygeyy Shaun Shawn Shann";
var myName = "Shaun";
var hits = [];

for(i=0; i < text.length; i++) { 
        for(x=0; x < myName.length; x++) {
            if(text[x+i] !== myName[x]) {
                break;
            }
            if(x === myName.length-1) {
                hits.push(myName);
            }
        } 
}

if(hits === 0) {
    console.log("Your name was not found.");
} else {
    console.log(hits);
    console.log("Your name has been found" + " " + hits.length +" times.");
}

EDIT 2: Also I was only pushing each letter one at a time because that's how the curriculum had me do it. Here below I changed it to simply remove the third for loop and push the entire name to the hits[] array.


#16

Here is the right answer:

/*jshint multistr:true */
text = "blah blah blah blah blah blah blah blah blah blah blah blah David blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah David blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah David blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah David blah blah blah blah blah blah blah blah blah blah blah";
var myName = "David";
var hits = [];

for (var i = 0; i < text.length; i++){
if (text[i] === myName[0]){
for (var j = i; j < (i + myName.length); j++){
hits.push(text[j]);
}
}
}


#17

Wouldn't that start pushing all of the following strings to hits even if only the first letters match and the rest don't? If text[i] is "D" and myName[0] is also "D" it will then begin a loop where it's adding every subsequent letter equal to the length of the rest of the name? The way I wrote it in my last post is very similar but only matches the exact name, not just the first letter.

Here is what I came out with after ionatan's suggestions(tested and working):

var text = "Shane Shawn SShauneany ShaunsdswfBlasgsdgtweyewyShaunsfgwetewtye Shaungfasgasgasdgy ShaneShaunsdfsafrShaun Shaun Shanesdgseygeyy Shaun Shawn Shann";
var myName = "Shaun";
var hits = [];

for(i=0; i < text.length; i++) { 
        for(x=0; x < myName.length; x++) {
            if(text[x+i] !== myName[x]) {
                break;
            }
            if(x === myName.length-1) {
                hits.push(myName);
            }
        } 
}

if(hits === 0) {
    console.log("Your name was not found.");
} else {
    console.log(hits);
    console.log("Your name has been found" + " " + hits.length +" times.");
}

#18

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