For some reason, my indexOf 2nd arg (where to start the search) is not working. It just always returns 4 or -1.
Where string test = "Bob jr" and I am using built-in JavaScript console on about:blank:
> var test = "Bob jr";
> test.indexOf('j', 0);
< 4 = $3
> test.indexOf('j', 1);
< 4 = $3
> test.indexOf('j', 12);
< -1 = $2
Why is this not working and how can I get it working?
Whether you start looking at 0 or index 1, the j is still at index 4.
Your final example proves the argument does work, because you said to start after the j (beyond the end of the string entirely), and sure enough, it didn't find it.
Let's see indexOf's second argument in action:
var str = "j and j and j x";
console.log("Search string: '" + str + "'");
for (var n = 0; n < str.length; ++n) {
test(str, n);
}
function test(s, start) {
var index = s.indexOf("j", start);
console.log("Starting at " + start + ": " + index);
}
If you want to find out how far after the index you've given it is to the j, you can do that in two ways:
Subtract your index from the result you get:
console.log("Distance: " + (test.indexOf('j', 1) - 1));
Search a substring:
console.log("Distance: " + test.substring(1).indexOf('j');
Check the documentation of indexOf here
str.indexOf(searchValue[, fromIndex])
There is no j after position 12 and that is why you are getting -1 in the last case.
indexOf always return the index within the calling String object of the first occurrence of the specified value, starting the search at fromIndex. The reason your return value isn't changing is because "j" is still the 5th character in your string, regardless of whether you begin your search a few characters into the string.
Related
I am taking the challenges from code-wars and I am looking at a solution and I don't understand it. Can somebody explain what s is doing as well as o?
function duplicateEncode(word) {
word = word.toLowerCase();
var c = '', s = '', o = '';
for (i = 0; i < word.length; i++) {
s = word.slice(i + 1);
o = s + word.slice(0, i);
c += (o.indexOf(word[i]) > -1) ? ')' : '(';
}
return c;
}
From String.prototype.slice MDN documentation:
beginIndex
The zero-based index at which to begin extraction. If
negative, it is treated as strLength + (beginIndex) where strLength is
the length of the string (for example, if beginIndex is -3 it is
treated as strLength - 3). If beginIndex is greater than or equal to
the length of the string, slice() returns an empty string.
endIndex
Optional. The zero-based index before which to end extraction. The
character at this index will not be included. If endIndex is omitted,
slice() extracts to the end of the string. If negative, it is treated
as strLength + endIndex where strLength is the length of the string
(for example, if endIndex is -3 it is treated as strLength - 3).
s = word.slice(i + 1);
o = s + word.slice(0, i);
these two lines get what's after the current character and what's before it and concatenate these two pieces. In other words, they build a string equal to the source string with the current char omitted. For example, if word is abcde and i=2, then o will be de + ab = deab. Of course, they could have simply written
o = word.slice(0, i) + word.slice(i + 1)
with the same effect.
As a side note, this algorithm appears quite inefficient as it builds word.length temporary strings just to check the uniqueness. A more idiomatic approach would be to use (last)indexOf along the lines of
function duplicateEncode(word) {
let w = [...word.toLowerCase()];
return w
.map(c => w.indexOf(c) === w.lastIndexOf(c) ? '(' : ')')
.join('')
}
s will contain all the characters in word after the character at the current iteration
o will contain all the characters in word except the one at the current iteration (s + [all the characters in word from start till the one at the current iteration]).
This means that the (o.indexOf(word[i]) > -1 ) expression will only be true if the character at the current iteration has a duplicate.
I created a function that takes a string converts the string to an array and then compares each string character to each vowel in an array, removing the string character if it matches one. It doesnt seems to be working correctly on longer words. For example with "tom" the o would be removed but with "johnson" only the first o is removed and then the n is removed at the end as well. I'm not seeing the issue.
function removeVolwels(string){
let strAr= function(string){
//converts to to lower case and turns string into an array
let s= string.toLowerCase();
let strAr= s.split("");
return strAr;
}(string);
//stores vowels
let vowels=["a","e","o","i","u","y"];
//loops through each character
for(let i=0; i < string.length -1; i++){
console.log("i index " + i);
//compares each character in the string to a every vowel until it matches one
for(let j=0; j < vowels.length; j++){
console.log("j index " + j + " and " +vowels[j]);
if(string[i] === vowels[j]){
console.log(string[i].toString() + " === "+vowels[j]);
console.log("removed " + string[i]);
//removes vowel if letter matches one
strAr.splice(i,1);
console.log(strAr)
}
}
}
return strAr.join("");
}
console.log('tom => ' + removeVolwels('tom'));
console.log('johnson => ' + removeVolwels('johnson'));
The problem is that you call strAr.splice(i,1);.
So, you have word "johnson", and after removing first "o" you've got "jhnson", but current length of string is 6 instead of 7 in the beginning!
When you get to next "o" - i have value of 5 (which is correct for "johnson" string but not "jhnson").
Also, there is another bug in loop - you have condition i < string.length -1. That means you will never reach last character. It should be i < string.length.
So, if you want to reuse your solution you can write something like this:
function removeVolwels(string){
let strAr= function(string){
//converts to to lower case and turns string into an array
let s= string.toLowerCase();
let strAr= s.split("");
return strAr;
}(string);
//stores vowels
let vowels=["a","e","o","i","u","y"];
let returnVal = [];
//loops through each character
for(let i=0; i < string.length; i++){
console.log("i index " + i);
// simple flag to match if letter should be added to return array
let shouldBeAdded = true;
//compares each character in the string to a every vowel until it matches one
for(let j=0; j < vowels.length; j++){
console.log("j index " + j + " and " +vowels[j]);
if(string[i] === vowels[j]){
// when it is some of the vowels it should not be added, so we change the flag, and break 'vowel loop'
shouldBeAdded = false;
break;
}
}
// if flag is true then add letter to result array
if(shouldBeAdded === true) {
returnVal.push(string[i])
}
}
return returnVal.join("");
}
console.log('tom => ' + removeVolwels('tom'));
console.log('johnson => ' + removeVolwels('johnson'));
You seem to be overcomplicating things a bit. Below is a much more streamlined way of doing what you're after (code commented).
function removeVowels(string) {
// convert string to lowercase and split into array 's'
let s = string.toLowerCase().split("");
// define our list of vowels
let vowels = ["a", "e", "o", "i", "u", "y"];
// loop over array 's' in reverse. if the letter we're iterating over is in the vowels array, remove it. We do this in reverse because we'd skip letters if we went from front to back due to the splice.
for (let i = s.length-1; i >= 0; i--) {
if (vowels.indexOf(s[i]) > -1) {
s.splice(i, 1); // 'i' is the index to start at (which we get from our loop) and 1 is the number of characters to remove.
}
}
return s.join("");
}
console.log('tom => ' + removeVowels('tom'));
console.log('johnson => ' + removeVowels('johnson'));
console.log('aoeieyyozoyyeieoa => ' + removeVowels('aoeieyyozoyyeieoa'));
Because after executing,
strAr.splice(i,1)
index in original string and index in strAr are not same for the same character.
So, you need to twist your logic for that.
Here's a simpler approach that utilizes Array.prototype.filter,Array.prototype.join, and Array.prototype.indexOf methods. The following code also uses String.prototype.split method to convert a string into a character array:
//1st param is the string you want to remove letters from
//2nd param is an array containing the letters to remove
function removeLetters(str, toRemove) {
//Create an array - each index contains a single character
let letters = str.split('');
//Use Array.prototype.filter method to remove any letter that occurs in "toRemove" array
let filtered = letters.filter(letter => toRemove.indexOf(letter) === -1)
//Turn the filtered array back into a string
return filtered.join('');
}
//The letters we want to remove are all vowels, so:
const vowels = ['a', 'e', 'i', 'o', 'u', 'y'];
//Some test cases
const word = "tommy";
const word2 = "johnson";
const word3 = "aeioux";
console.log(removeLetters(word, vowels));
console.log(removeLetters(word2, vowels));
console.log(removeLetters(word3, vowels));
I'm playing around with PEG.js.
This is my grammar:
start = expression
expression = a:[a-z]+
{return a.join("");}
When I execute it in my browser:
obj = parser.parse("test");
for (var i = 0; i <= obj.length; i++) {
console.log(i + " - " + obj[i])
}
I get this output:
0 - t
1 - e
2 - s
3 - t
4 - undefined
Why isn't it joined to only 1 word, even though I used return a.join("") in my grammar?
parser.parse does return the single word "test"; you are just printing it one character at a time.
Did you mean to do this?
var result = parser.parse("test");
console.log(result) // "test"
To directly answer your question, you're getting one letter each iteration because a string acts like an array. So you're accessing one letter at a time by using obj[i] Try this to get one word returned.
obj = parser.parse("test");
for (var i = 0; i <= obj.length; i++) {
console.log(i + " - " + obj)
}
I have this code :
function list(target, letters, lvls) {
var index = 0;
(function iter(s, lvl) {
if(lvl++ == lvls)
return target.appendChild(document.createTextNode(
++index + ' - ' + s + '\n'
));
for(var i=0; i<letters.length; ++i)
iter(s + letters[i], lvl);
})('', 0);
}
list(document.getElementById('output'), 'abc', 3);
But I don't know this type of function syntax.
Can some one explain to me the function behavior and what this code exactly do step by step.
And thanks in advance
This seems to be iterating through the string 'abc' and creating as many X letter strings as possible with the combination of all the characters in the string.
So the call is list([element ID to output strings], [string of all possible letters], [size of strings to generate])
So the following example -
<script type="text/javascript">
function list(target, letters, lvls) {
var index = 0;
(function iter(s, lvl) {
if(lvl++ == lvls)
return target.appendChild(document.createTextNode(
++index + ' - ' + s + '\n'
));
for(var i=0; i<letters.length; ++i)
iter(s + letters[i], lvl);
})('', 0);
}
list(document.getElementById('output'), 'ab', 2);
</script>
<div id="output"></div>
will output all possible two letter strings (defined by param 3), using the characters from the input string (param 2) and will result in -
1 - aa 2 - ab 3 - ba 4 - bb
Explanation
Inside the method there is a second called iter with the arguments s and lvls. On
first run, the arguments parsed to the iter method are blank and 0. It hits the for
loop which runs until all of the letters in the string letters have been used up,
each time recursively calling the iter method. Each time it adds the current letter in
the iteration s, along with the next letter in the string letters[i]. Every time it
recursively calls itself it builds up the string until the number of specified levels have
been reached for that particular string and then returns the result, along with the index
value. This is just a numeric value to represent the string count.
I have string looking like this:
01
02
03
99
I'd like to parse these to make them into strings like:
1. 2. 3. 99. etc.
The numbers are a maximum of 2 characters. Also I have to parse some more numbers later in the source string so I would like to learn the substring equivalent in javascript. Can someone give me advice on how I can do. Previously I had been doing it in C# with the following:
int.Parse(RowKey.Substring(0, 2)).ToString() + "."
Thanks
Why, parseInt of course.
// Add 2 until end of string
var originalA = "01020399";
for (var i = 0; i < originalA.length; i += 2)
{
document.write(parseInt(originalA.substr(i, 2), 10) + ". ");
}
// Split on carriage returns
var originalB = "01\n02\n03\n99";
var strArrayB = originalB.split("\n");
for (var i = 0; i < strArrayB.length; i++)
{
document.write(parseInt(strArrayB[i], 10) + ". ");
}
// Replace the leading zero with regular expressions
var originalC = "01\n02\n03\n99";
var strArrayC = originalC.split("\n");
var regExpC = /^0/;
for (var i = 0; i < strArrayC.length; i++)
{
document.write(strArrayC[i].replace(regExpC, "") + ". ");
}
The other notes are that JavaScript is weakly typed, so "a" + 1 returns "a1". Additionally, for substrings you can choose between substring(start, end) and substr(start, length). If you're just trying to pull a single character, "abcdefg"[2] will return "c" (zero-based index, so 2 means the third character). You usually won't have to worry about type-casting when it comes to simple numbers or letters.
http://jsfiddle.net/mbwt4/3/
use parseInt function.
parseInt(09) //this will give you 9
var myString = parseInt("09").toString()+". "+parseInt("08").toString();
string = '01\n02\n03\n99';
array = string.split('\n');
string2 = '';
for (i = 0; i < array.length; i++) {
array[i] = parseInt(array[i]);
string2 += array[i] + '. ';
}
document.write(string2);
var number = parseFloat('0099');
Demo
Substring in JavaScript works like this:
string.substring(from, to);
where from is inclusive and to is exclusive. You can also use slice:
string.slice(from, to)
where from is inclusive and to is exclusive. The difference between slice and substring is with slice you can specify negative numbers. For example, from = -1 indicates the last character. from(-1, -3) would give you the last 2 characters of the string.
With both methods if you don't specify end then you will get all the characters to the end.
Paul
Ii they are always 2 digits how about;
var s = "01020399";
var result = []
for (var i = 0; i < s.length; i+=2)
result.push(parseInt(s.substr(i, 2), 10) + ".")
alert( result[2] ) // 3.
alert( result.join(" ") ) // 1. 2. 3. 99.