Understanding the .length property - javascript

Could someone please explain what the .length property is doing in the following code:
let sentenceCount = 0;
betterWords.forEach(word => {
if (word[word.length-1] === '.' || word[word.length-1] === '!') {
sentenceCount++;
}
});
I understand the basic idea of what .length does, but when I try to print out word[word.length], it prints out as undefined. If I print out word[word.length-1], then I get the . and ! in the text. I'm not understanding what word[word.length-1] actually is so that when -1 is attached it gets the characters on the end.
Thank you in advance for any advice on this.

JavaScript exhibits zero based indexing, that is, the first element in an array or in a string is at position 0. Therefore, an array or string of length n has elements going from position 0 to n - 1, with element at position n being undefined. This means that an array or string with n elements has the last element at n - 1, which is accessed as someArrayString[n - 1].
.length returns the length of an array or a string. Hence, the last element of an array or a string is found at someArrayString.length - 1 which is accessed as someArrayString[someArrayString.length - 1].
From the code, it can be inferred that word is a string. Therefore, the line word[word.length-1] accesses the last char (letter) in the word (although it actually accesses the last code unit
but in ASCII a code unit correspond with a 1 byte ASCII char).
For example, the string var word = "JavaScript" has length 10. With J at position 0 and t at position 9. In other words, word[0] == 'J' and word[word.length - 1] == 't'

Let's say your word = 'People';
word.length would return 6 which is the character number in your word.
Since arrays (in this case string because .length can be used in strings too) start from index 0, word.length-1 would give you the 5th element of your string, which is the last character of your word.
In your code, if (word[word.length-1] === '.' || word[word.length-1] === '!') checks if the last character of a word is a dot (.) or exclamation point (!) so you can count how many sentences there are in a given string.

word.length-1 - Returns the last index in the word
Explanation
word= 'test!';
console.log(word[word.length-1])
OUTPUT - !
The Length of word = 5
We need to get the last index of the word i.e word[4] as the array indexing starts from 0

Your .length property returns the length of the string. The string itself is a one-dimensional array with elements of the type character so using .length gives the size of the array. Arrays use zero-based indexing.
So in your case word[word.length-1] returns the last element/character of the array and word[word.length] goes beyond the bounds of the array and that's why it prints out undefined.
Here's a playground you can test it.
const string = "Just a test.";
//get the last element
console.log(string[string.length-1]);
//trying to get an element outside the bounds of the array
console.log(string[string.length]);

Alright, In your code I assume that betterWords is an array because you are using forEach.
And also assume the betterWords array is something like,
betterWords = ['word.','words!','hello','world'];
Length Property
The length property returns the length of array or string.
let myArray = [0,5,6,8,9];
let myString = 'hello';
console.log(myArray.length) // 5 | because myArray has total 5 elements.
console.log(myString .length) // 5 | because myString has total 5 characters.
Index
Then index tells us the position of an element in an array or a character in a string.
The index is starting from 0.
let myString = 'hello';
/*
* h e l l o
* - - - - -
* 0 1 2 3 4
*/
console.log(myString[0]); // h | because h is 0 index of hello
So now you can see the length of the word hello is 5. But the last index of the word hellois4`. Which means the last index = length - 1
That's why here we are subtracting 1 from length to get the last index.
console.log(word[word.length-1]);

Related

How do I replace a letter that is 15 chars ahead of each other?

I am trying to replace each character a user inputs that is 15 letters ahead in the alphabet. For example, if a user inputs the word A, then it would output "P".
the word "AB" would output "PQ" and so on with every word.
I've tried the following code but it is not working. I am thinking a loop may be the answer, but if anyone can think of some better ideas let me know.
alphabetArray = ["abcdefghijklmnopqrstuvwyxz"];
function jumpAhead15(aString){
aString.replace(alphabetArray[0][aString + 15]);
}
jumpAhead15("hi");
You could take the string as iterable and get an array of characters and replace any character by getting the index and the offset, adjusted by the remainder of the length of the alphabet.
The reminder operator % returns the rest of a division:
The remainder operator returns the remainder left over when one operand is divided by a second operand. It always takes the sign of the dividend.
The function is here to keep the index for the getting the character of alphabet in a valid range. For example by taking index 20 and the wanted shift of 15, you get 35 which is not an index of alphabet. by using the remainder operator you get the value of 9 which is the rest of 35 / 26 = 1 rest 9
Then return the character and join the array to a final string.
Method used:
Array.from, which takes two arguments, one iterable or an object with a length property and a mappring function, which is called for every element of the new array. (c is the first parameter of the callback and denotes here a single character)
arrow function as callback for Array.from
function jumpAhead15(aString) {
var alphabet = "abcdefghijklmnopqrstuvwyxz";
return Array
.from(
aString,
c => alphabet[(alphabet.indexOf(c) + 15) % alphabet.length]
)
.join('');
}
console.log(jumpAhead15("hi"));
console.log(jumpAhead15("ab"));
With alphabetArray as above, try:
aString.split("").map(letter => alphabetArray[(alphabetArray.indexOf(letter) + 15) % 26]).join("");
That is: convert the string to an array of 1-letter strings, replace each letter by the one 15 places further along (wrapping if necessary, hence the modulus operator %), then join the letters back together into one string.
If you find the answer from Nina hard to understand, then this one may not be for you either, but here is a function that is built on a more generic letter rotation scheme. It also handles differences in case:
const rotate = (configs) => (str) => str.split('').map(
c => configs.reduce(
(s, [letters, offset]) => {
const idx = letters.indexOf(s);
return idx < 0 ? s : letters[(idx + offset) % letters.length]
},
c
)
).join('')
const by15 = rotate([
[[...'abcdefghijklmnopqrstuvwxyz'], 15],
[[...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'], 15]
])
console.log(by15('ab')) //~> 'pq'
console.log(by15('aB')) //~> 'pQ'
console.log(by15('Hello, world!')) //~> 'Wtaad, ldgas!'
This uses the same basic technique with the modulus operator, modified slightly to return the original character if it's not in our list. We do this for each alphabet supplied, in this case, the upper- and lower-case letters. This only works if the different alphabets have no overlap. We pass the offset together with each alphabet, in case you want to, for instance, rotate digits by 3 and letters by 15. If you didn't want to do this, you could move the offset out of the configs parameter (in which case it might be called alphabets) and make the single offset a second parameter for rotate.
Note the structure: rotate is an arrow function which returns an arrow function. So to get a useful function out of it, you need to call it with the alphabet configuration. The function returned just takes a string and returns the rotated string.
This is not the most efficient solution, as you have to loop through each alphabet, even once you've found it. Since I wouldn't expect it to be used with many alphabets, this seems a good tradeoff for relatively clean code. But one could easily write a version which searched through until it found an alphabet that contained your character and then worked on that one. This is left as an exercise for the reader.

Searching for empty string in str.indexOf() in javascript

Searching for the empty string using String.indexOf(searchValue[,fromindex]) returns unexpected results as given in the following snippet.
console.log('foo'.indexOf('')) // 0
console.log('foo'.indexOf('',2)) // 2
console.log('foo'.indexOf('',3)) // 3
console.log('foo'.indexOf('',4)) // 3
console.log('foo'.indexOf('',100)) // 3
It searches for the first match, starting at the position given with the second argument (the fromIndex - if any). But the empty string will always be matched as soon as possible; it's an empty string, after all. When you provide a fromIndex greater than the length of the string, it simply runs the test as if the fromIndex was the length of the string:
An integer representing the index at which to start the search; the default value is 0. For fromIndex values lower than 0 or greater than str.length, the search starts at index 0 and str.length respectively.
Empty string exist everywhere, for example for your first log, the empty string exist in first of string, you can think of "foo" as "" + "foo", same as other logs. basically indexOf returns the index of the first occurrence of the character in the character sequence represented by this object, or -1 if the character does not occur.

How does this for loop and if statement work?

Trying to figure out in my own understanding how the for loop and if statement of this function work. This is so because having googled the challenge, this code is shorter but same result as my initial one. The confusion is at the longest variable. It stores the longest lengths of the words greater than str.length(5) - or I may be wrong. For some ununderstood reason, the length of language(8) is not stored in the variable although 5, 10 and 18 are.
function longestWord(str) {
str = str.split(" ");
var longest = 0;
var word = null;
for (var i = 0; i < str.length; i++) {
if (longest < str[i].length) {
console.log("str = " + str[i]);
longest = str[i].length;
console.log("longest = " + longest); //What happended to 8 for language?
word = str[i];
}
}
return word;
}
console.log(longestWord("Using the JavaScript language bademnostalgiastic"));
All this does it keep track of the longest word (and stores the char count in longest). For each iteration, it tests to see if the next string has more characters than the currently recorded longest string (determined by longest). If it does, it stores the new char count as it is the new "winner of being the longest".
Here's what's happening here:
take a string and split it up into words (determined by spaces)
at this point you have a string array of all the individual strings divided by " "
loop through all of the strings in the array
if the current string that you are iterating through has character counter more than any other previous ones, then store this current character count in the variable longest
continue the loop and use the above logic in the previous point
So at the end of this all you have the actual string (stored in word) and the character count (stored in longest) of the word with the most characters.
JavaScript is 10 characters long and is tested before language, so the if test fails and it is skipped.
It stores the longest lengths of the words greater than str.length(5)
No. It stores the longest length seen so far. It gets 5 when Using is tested, but that is quickly overwritten.
The length of "JavaScript" is 10, which is longer than "language". Since "JavaScript" comes first, "language" won't be longer than the longest, so the if statement will result in false.
array str[]={Using, the,JavaScript, language ,bademnostalgiastic}
Iteration 1
str[i]=Using
str.length=5 (a)
Longest =0 (b)
since (a)>(b)
Longest =5
word=Using
Iteration 2
str[i]=the
str.length=3 (a)
Longest =5 (b)
since (a)<(b)
Longest and word remain same
so,Longest =5
and,word=Using
Iteration 3
str[i]=JavaScript
str.length=10 (a)
Longest =5 (b)
since (a)>(b)
so,Longest =10
and,word=JavaScript
Iteration4
str[i]=language
str.length=8 (a)
Longest =10 (b)
since (a)<(b)
so longest remain same
so,Longest =10
and,word=JavaScript
Iteration5
str[i]=bademnostalgiastic
str.length=18 (a)
Longest =10 (b)
since (a)>(b)
so,Longest =18
and,word=bademnostalgiastic
END OF LOOP
so longest word bademnostalgiastic
Here's a breakdown:
str = str.split(" ");
This is making an array of strings split on spaces.
for (var i = 0; i < str.length; i++)
We're starting here with i (the iterator variable) at 0. We're going to keep doing this loop while i is less than the length of str. We're going to increase i by 1 each time we go through this loop.
if (longest < str[i].length)
Here we check if the longest we've saved is less than the string's length we're looking at.
longest = str[i].length;
Here we assign the new longest string, because this one is longer.
word = str[i];
We also save the word, likely so we can use it later.
return word;
After the loop ends, we're going to send word back as the result.
console.log(longestWord("Using the JavaScript language bademnostalgiastic"));
This is your call and print statement.
The reason you're seeing 5, 10, and 18, is because you're only printing out values when the value is bigger than what you've already seen.

I need an explanation on slice()

I was completing javascript exercises and got stuck on creating a function which checks if a string is a palindrome. For your reference, this was the given solution.
I understand what slice() does as a method, and I followed the function here until the point where it checks to see if the first letter matches the last.
if (cstr[x] != cstr.slice(-1-x)[0])
What is going on with the parameter values of the slice method? I was expecting the parameters to slice the last letter and I presume it does but I would appreciate some help in pointing out how!
Let's pop open the console and take a look!
> var s = 'abcde'
"abcde"
> s[0]
"a"
> s.slice(-1)
"e"
> s.slice(-1)[0]
"e"
> s[1]
"b"
> s.slice(-1 - 1)
"de"
> s.slice(-1 - 1)[0]
"d"
As I hope you can see by now, slicing with a negative number -n will return the last n characters of the string, with n = 1 being the last character. So to have the palindrome test work correctly, you need to slice at -1 - x (the "x-th from last" character).
arr.slice([begin[, end]])
Parameters
begin
Zero-based index at which to begin extraction. As a negative index, begin indicates an offset from the end of the sequence. slice(-2) extracts the last two elements in the sequence. If begin is omitted, slice begins from index 0.
end
Zero-based index at which to end extraction. slice extracts up to but not including end. slice(1,4) extracts the second element up to the fourth element (elements indexed 1, 2, and 3). As a negative index, end indicates an offset from the end of the sequence. slice(2,-1) extracts the third element through the second-to-last element in the sequence. If end is omitted, slice extracts to the end of the sequence (arr.length).
Description
slice returns a shallow copy of elements from the original array. Elements of the original array are copied into the returned array as follows:
For object references (and not the actual object), slice copies object references into the new array. Both the original and new array refer to the same object. If a referenced object changes, the changes are visible to both the new and original arrays.
For strings and numbers (not String and Number objects), slice copies strings and numbers into the new array. Changes to the string or number in one array does not affect the other array.
If a new element is added to either array, the other array is not affected.

How to find a "(a substring)" in a given "text" without using Regular expressions?

Recently I was asked in an interview, where the interviewer asked me this above question.
I was surely perplexed and answered him by using a for loop implementation where
we would find the length of the given "text" (using JavaScript) ... str.length() ...
we would take the first element of the "pattern" and find that in the "text".
If found we would increment the array .. As strings are stored as array in JavaScript ..
And we would find the "(a substring)" in similar way..
know this might be wrong way , but can anyone suggest a better way ? Thank you :-)
String.prototype.search (regexp)
When the search method is called with argument regexp, the following steps are taken:
Call CheckObjectCoercible passing the this value as its argument.
Let string be the result of calling ToString, giving it the this value as its argument.
If Type(regexp) is Object and the value of the [[Class]] internal property of regexp is "RegExp", then let rx be regexp;
Else, let rx be a new RegExp object created as if by the expression new RegExp(regexp) where RegExp is the standard built-in constructor with that name.
Search the value string from its beginning for an occurrence of the regular expression pattern rx. Let result be a Number indicating the offset within string where the pattern matched, or –1 if there was no match. The lastIndex and global properties of regexp are ignored when performing the search. The lastIndex property of regexp is left unchanged.
Return result.
Or if you want to avoid the word RegExp alltogether and search for a sub-string then
String.prototype.indexOf (searchString, position)
If searchString appears as a substring of the result of converting this object to a String, at one or more positions that are greater than or equal to position, then the index of the smallest such position is returned; otherwise, ‑1 is returned. If position is undefined, 0 is assumed, so as to search all of the String.
The indexOf method takes two arguments, searchString and position, and performs the following steps:
Call CheckObjectCoercible passing the this value as its argument.
Let S be the result of calling ToString, giving it the this value as its argument.
Let searchStr be ToString(searchString).
Let pos be ToInteger(position). (If position is undefined, this step produces the value 0).
Let len be the number of characters in S.
Let start be min(max(pos, 0), len).
Let searchLen be the number of characters in searchStr.
Return the smallest possible integer k not smaller than start such that k+ searchLen is not greater than len, and for all nonnegative integers j less than searchLen, the character at position k+j of S is the same as the character at position j of searchStr; but if there is no such integer k, then return the value -1.
I think the answer depends on the context, and the context seems to be lacking.
If the question was about algorithms, then I believe your best choice of algorithms (i.e., the fastest algorithm) is Boyer–Moore string search.
If the question was a HowTo in PHP, then its probably string.indexOf. And str.search would probably not be a valid answer since it takes a regex.
S[i] refers to the character at index i of string S, counting from 1.
S[i..j] refers to the substring of string S starting at index i and ending at j, inclusive.
A prefix of S is a substring S[1..i] for some i in range [1, n], where n is the length of S.
A suffix of S is a substring S[i..n] for some i in range [1, n], where n is the length of S.
The string to be searched for is called the pattern and is referred to with symbol P.
The string being searched in is called the text and is referred to with symbol T.
The length of P is n.
The length of T is m.
An alignment of P to T is an index k in T such that the last character of P is aligned with index k of T.
A match or occurrence of P occurs at an alignment if P is equivalent to T[(k-n+1)..k].

Categories

Resources