I am trying to get the count of the most repeated letter in a word
function GreatestCount(str)
{
var count = {}
for (var i = 0 ; i<str.length;i++)
{
var char = str[i];
count[char] = (count[char] || 0) + 1;
}
//get the largest number for the letter counts
var max = 0;
for (var c in count) {
if (count[c] > max) max = count[c];
}
return max
}
can someone explain to me why
count[char] = (count[char] || 0) + 1;// this works
count[char] += 1 // this does not work
Because
count[char] += 1
is equal to
count[char] = count[char] + 1
and the first time the code is run, count[char] is undefined so it's pretty much the same as
undefined + 1 // which is NaN
The working version circumvents this case by safely adding with 0 using || operator.
Initially, count is an empty object†, so it doesn't have the char property. Therefore, count[char] returns undefined.
And undefined + 1 produces NaN.
Therefore, you must inititialize it to 0 in order to make it work properly.
†: count is not really an empty object because it inherits properties from Object.prototype. It would be problematic if a char property is defined there. I recommend using count = Object.create(null) instead.
You need to initialize your count[char] to zero before incrementing it.
On first occurrence count[char] is undefined and undefined += 1 !== 1
As other said your variable is not initialize in the beginning
so count[char] +=1 is not working, but when you do (count[char] || 0) you actually tell them that you want to set 0 if the variable is "false". False could mean undefined, NaN, 0.
Related
let str = "Hello world";
let target = "o";
let pos = -1;
while ((pos = str.indexOf(target, pos + 1)) != -1) {
console.log( pos );
}
When pos is - 1 it works fine, but when I set 0 and remove + 1 it returns endless 4. Why does it happen?
If you do not increase the position, it repeats 4 indefinitely because you are always doing the exact same check. Removing variables and using just this part:
pos = str.indexOf(target, pos)
This would mean:
str.indexOf(target, 0) // Returns 4
str.indexOf(target, 4) // Returns 4
str.indexOf(target, 4) // etc
That's because indexOf will start looking at the exact index that it just found so it will find the o again. Adding +1 makes sure that it continues looking PAST last occurence found.
code:
function OneDecremented(num) {
num = num.toString()
var count = 0
for(i = 1; i < num.length; i++) {
if(num[i - 1] - num[i] === 1){
count++
}
}
return count
}
console.log(OneDecremented(9876541110))
so I'm struggling to understand two things:
what's the difference between i and num[i]
I don't understand how the calculation is happening inside the if statement, could someone break it down?
sorry if these questions sound too silly, I'm new to JS and couldn't really get my head around the arithmetic calculations. Thank you for you time.
That code is poorly written for few reasons, but most importantly, it leaks the i reference globally so, let's start with a better version:
function OneDecremented(num) {
var str = num.toString();
var count = 0;
for(var i = 1; i < str.length; i++) {
if(str[i - 1] - str[i] === 1)
count++;
}
return count;
}
Strings, in modern JS, can be accessed like arrays, and the index returns the char at the index position:
if(str[i - 1] - str[i] === 1)
// is the same as
if ((str.charAt(i - 1) - str.charAt(i)) === 1)
Once retrieved each char, the code does an implicit "char to number" conversion, thanks to the - operator, but if it was a + instead, it would've concatenated the two chars as string instead (so, be careful).
It's always better to be explicit, but if you know how - works, it does the job for this task.
The loop starts from 1, and it checks that the char at i - 1, which is in the first iteration the char at index 0, minus the current char, is 1, meaning the current char is one less the previous.
When that's the case, the counter sums up.
Andrea and Mitya already nailed it.
The next step could be switching to a first class based approach like using a specific Array method such as reduce.
Such an approach, if implemented correctly, usually improves readability/maintainability of code and allows for better code-reuse.
For the example provided by the OP one could write two functions, the actual method, which gets the count and the above mentioned first class reducer functionality. Since reduce is a standard way of how arrays can be processed the arguments-precedence of the reducer/callback is well specified too ...
[/* ... */].reduce(function(accumulator, currentValue, currentIndex, currentlyProcessedArray) {
// implement reducer/aggregation/accumulator logic here.
// the return value serves as the
// new `accumulator` value within
// the next iteration step.
// thus, always return something! ... e.g ...
return (accumulator + currentValue);
});
function aggregatePrecursorAndDecrementedSuccessorCount(count, char, idx, arr) {
const precursorValue = Number(arr[idx - 1]);
const incrementedCurrentValue = (Number(char) + 1);
const isValidCount = (precursorValue === incrementedCurrentValue);
return (count + (isValidCount ? 1 : 0));
//return (count + Number(isValidCount)); // cast boolean value to either 1 or 0.
}
function getPrecursorAndDecrementedSuccessorCount(int) {
return String(int) // - assure/typecast always a/into string value.
.split('') // - split string value into an array of single characters.
.reduce(aggregatePrecursorAndDecrementedSuccessorCount, 0);
}
console.log(getPrecursorAndDecrementedSuccessorCount(9876541110));
.as-console-wrapper { min-height: 100%!important; top: 0; }
what's the difference between i and num[i]
i is the iteration key, i.e. 0, 1, 2 etc, for as many characters are in the stringified number. num[i] is the character at the index i in the string, i.e. num[i] where i is 0 == 9 (the character in the string at index 0).
I don't understand how the calculation is happening inside the if statement, could someone break it down?
That says: If the calculation of the number at index i-1 of the string, minus the current number being considered (at index i in the string) minus is 1, then increment count.
Step by step for the actual number used:
9 - has no previous character; calculation (undefined - 9) does not equate to 1
8 - previous char is 9; (9 - 8) == 1; increment count
7 - ditto
6 - ditto
5 - ditto
4 - ditto
1 - previous char is 4; calculation (4 - 1) does not equate to 1
1 - previous char is 1; calculation (1 - 1) does not equate to 1
1 - ditto
0 - previous char is 1; (1 - 0) == 1; increment count
I'm writing a function that will return true or false in regards to whether or not the input string is in alphabetical order. I'm getting undefined and not sure what I'm missing
function is_alphabetic(str) {
let result = true;
for (let count = 1, other_count = 2; count >= str.length - 1, other_count >= str.length; count++,
other_count++) {
if (str.at[count] > str.at[other_count]) {
let result = false
}
return result
}
}
console.log(is_alphabetic('abc'));
you have put return statement inside the for loop, it should be outside the loop body.
Your code is also not correct. count should start from 0, other_count should start from 1.
count >= str.length - 1 should be count < str.length - 1 (this condition is completely unnecessary in your code because other_count < str.length should be the terminating condition in the loop)
and
other_count >= str.length should be other_count < str.length
Here's your corrected code
function is_alphabetic(str) {
let result = true;
for (let count = 0, other_count = 1; other_count < str.length; count++, other_count++) {
if (str[count] > str[other_count]) {
result = false
}
}
return result;
}
console.log(is_alphabetic('abc'));
Here's an alternative approach
function is_alphabetic(str){
return str.split('')
.every((c, idx) => str[idx + 1] ? c < str[idx + 1] : true);
}
console.log(is_alphabetic('abc'));
Keep in mind that if you want the comparisons between the characters to be case-insensitive, then convert the string in to lowercase before comparing the characters.
I think is easier if you compare the string using this function:
var sortAlphabets = function(text) {
return text.split('').sort().join('');
};
This produces results like:
sortAlphabets("abghi")
output: "abghi"
Or:
sortAlphabets("ibvjpqjk")
output: "bijjkpqv"
if you want to know if your string is alphabetically sorted, you might use:
var myString = "abcezxy"
sortAlphabets(myString) == myString
output: false
Or in case, you want to create an specific function:
function isSorted(myString) {
return sortAlphabets(myString) == myString
}
And for that case, you can use:
isSorted("abc")
var sortAlphabets = function(text) {
return text.split('').sort().join('');
};
function isSorted(myString) {
return sortAlphabets(myString) == myString
}
alert("is abc sorted: " + isSorted("abc"));
alert("is axb sorted: " + isSorted("axb"));
This should do it. I used .localeCompare() as this will ignore small/capital differences and will also deal reasonably with language specific characters, like German Umlauts.
function is_alphabetic(str){
return !str.split('').some((v,i,a)=>i&&v.localeCompare(a[i-1])<0)
}
['abcdefg','aacccRt','ashhe','xyz','aüv'].forEach(s=> console.log(s,is_alphabetic(s)) );
There are two issues in your code:
Your return statement is in your for-loop. To avoid such mistakes you can get a code-formatter like prettier;
Your for-loop condition is invalid. Keep in mind that the second part of the for-loop statement is supposed to be true to do an iteration and false to stop doing iterations. In this case, your condition count >= str.length-1, other_count >= str.length will first evaluate count >= str.length-1, discard the result because of the comma operator, evaluate other_count >= str.length which immediately resolves to false.
These two things together make it so your function never returns, which the javascript runtime interprets as undefined.
Hope this helps you understand what went wrong. But like many other pointed out, there are better ways to tackle the problem you're trying to solve.
You just have to compare the string with its corresponding 'sorted' one
let string = 'abc'.split('').join('');
let sortedString = 'abc'.split('').sort().join('');
console.log(sortedString === sortedString)
let string2 = 'dbc'.split('').join('');
let sortedString2 = 'dbc'.split('').sort().join('');
console.log(string2 === sortedString2)
I have what I think surely is a really simple question for most of you. But I have some trouble to get my head around this for loop. What does the -1 in argument.length -1 stand for? Is it the last item? And the i-- that is for decrease by 1?
var plus = function() {
var sum = 0;
for (var i = arguments.length - 1; i >= 0; i--) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2,2,3,657,5643,4465,2,45,6));
When you call arguments.length It will return you the number of elements with the last one accessed with arguments[arguments.length-1] because counting starts with 0.
(the First element is accessed like this arguments[0]).
Here is good documentation for Java but it is the same for JavaScript: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
And yes i-- decreases i for 1. It is different i-- and --i.
Using ++/-- After the Operand
When you use the increment/decrement operator after the operand, the value will be returned before the operand is increased/decreased.
Check out this example:
// Increment
let a = 1;
console.log(a++); // 1
console.log(a); // 2
// Decrement
let b = 1;
console.log(b--); // 1
console.log(b); // 0
When we first log out the value of a, or b, neither has changed. That’s because the original value of the operand is being returned prior to the operand being changed. The next time the operator is used, we get the result of the +1, or -1.
Using ++/-- Before the Operand
If you’d rather make the variable increment/decrement before returning, you simply have to use the increment/decrement operator before the operand:
// Increment
let a = 1;
console.log(++a); // 2
console.log(a); // 2
// Decrement
let b = 1;
console.log(--b); // 0
console.log(b); // 0
As you can see in the above example, but using ++ or -- prior to our variable, the operation executes and adds/subtracts 1 prior to returning. This allows us to instantly log out and see the resulting value.
The - 1 means to subtract 1 from arguments.length. i-- means to decrease i by 1.
You need to know two things here:
arguments is a object type so it has key-value pair of values you passed as a argument into a function. Furthermore, the arguments object is not an Array. It is similar to an Array, but does not have any Array properties except length.
The key of arguments always starts with 0 and ends with one value less than the length of arguments. See the example below the key ends at 8 so you do arguments.length - 1 so that you get 8 instead of 9.
And since you are looping considering the last value first in arguments you do --i.
var plus = function() {
console.log(arguments);
console.log(typeof arguments);
var sum = 0;
for (var i = arguments.length - 1; i >= 0; i--) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2, 2, 3, 657, 5643, 4465, 2, 45, 6));
Alternatively, you can also do i++ as,
var plus = function() {
var sum = 0;
for (var i = 0; i <arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2, 2, 3, 657, 5643, 4465, 2, 45, 6));
I'm trying to insert a dash between even numbers. However, the program returns nothing when run. When I set the initial list to contain a number, it returns that same number indicating the loop isn't adding anything.
function dashEvenNumbers(numbers) {
var list = [];
for (var i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 == 0 && numbers[i + 1] == 0) {
list.push(i, '-');
} else {
list.push(i);
};
};
alert(list);
return list.join('');
};
alert(dashEvenNumbers(123125422));
You could use a regular expression with look ahead.
console.log('123125422'.replace(/([02468](?=[02468]))/g, '$1-'));
Numbers don't have a length property so numbers.length will be undefined.
You probably want to cast to string first, e.g.:
numbers = String(numbers);