Why Javascript console.log result is undefined while reversing the string? - javascript

var a = "gsdgtrshghf";
function reverseString(strr){
if (!strr.length){
var result="";
for(var i=strr.length;i>0;i++){
var a=strr.chatAt(i);
result+=a;
}
}return result;
}
console.log(reverseString(a))
When I tried to run it it returned me "undefined". I wonder what's the problem here.

The main reason is you are declaring var result="" and returning from outside of if(so it become undefined as its scope is only inside if statement) and other errors areas mention in comments you have a typo, charAt not chatAt. You can also simply use strr[i] to get the char. Also, you should do i-- and i >= 0 if you start at strr.length, otherwise for loop is immediately completed at the condition check. Check the below code.
var a = "gsdgtrshghf";
function reverseString(strr){
var result="";
if (strr.length){
for(var i=strr.length-1;i>=0;i--){
var a=strr.charAt(i);
result+=a;
}
}
return result;
}
console.log(reverseString(a))

Have a look:
var a = "gsdgtrshghf";
function reverseString(strr) {
var result = "";
if (strr.length != null) {
for (var i = strr.length - 1; i >= 0; i--) {
var a = strr.charAt(i);
result += a;
}
}
return result;
}
console.log(reverseString(a));
// Better
const reverse = str => Array.from(str).reverse().join('');
console.log(reverse('foo 饾寙 bar ma帽ana man虄ana'));
Explanation
It's charAt(i) not chatAt(i)
Loop should start from length - 1 and end at 0 and i should be decremented
And finally declare the variable outside of if
i.e for(var i = strr.length - ; i >= 0; i--){
not for(var i=strr.length;i>0;i++){
Better yet, use combo of Array.from(str).reverse().join(''), as it even works with Unicode characters, as pointed out in comments by gaetanoM

Related

tried to repeating the double letter of any string.ex- "hello" --> 'hheelloo' but stucked at for loop, any solution?

function doubleChar(str) {
var splt = str.split("");
for(var i=0;i<splt.length-1;i++){
var rpt= splt[i].repeat(2);
return rpt.join('');
}
}
console.log("hello");
An Haskellesque approach here just for fun...
var str = "hello",
double = ([c,...cs]) => c ? cs.length ? c + c + double(cs) : c + c : "";
console.log(double(str));
There were few problems in your code :
function doubleChar(str) {
var splt = str.split("");
for(var i=0;i<splt.length-1;i++){
var rpt= splt[i].repeat(2);
return rpt.join('');
}
}
console.log("hello");
first is that the code prints string "Hello" no matter what function doubleChar does.
in order to make console.log print result of doubleChar function you need to change it to this
console.log(doubleChar("Hello"))
now your code would call doubleChar function with the string "Hello" as input of function doubleChar and print the output of the function.
Now in your function, the return should not be inside of the loop, when the return is inside the loop, function sends the result of first iteration and there would be no other iterations
function doubleChar(str) {
var splt = str.split("");
for(var i=0;i<splt.length-1;i++){
var rpt= splt[i].repeat(2);
}
return rpt.join('');
}
console.log(doubleChar("hello"));
.join('') is for arrays when you want to mix all elements into a string but rpt is not an array but a string so you can just return rpt itself :
function doubleChar(str) {
var splt = str.split("");
for(var i=0;i<splt.length-1;i++){
var rpt= splt[i].repeat(2);
}
return rpt
}
console.log(doubleChar("hello"));
you also should not use var inside the loop because by doing so the javascript redefines the rpt and all previous values are lost so you can declare variable outside the loop and append new values inside the loop
function doubleChar(str) {
var splt = str.split("");
var rpt=''
for(var i=0;i<splt.length-1;i++){
rpt += splt[i].repeat(2);
}
return rpt
}
console.log(doubleChar("hello"));
now as final fix, inside your loop you're using i<splt.length-1 this probably because length is one more than maximum index but considering that you are using < instead of <= this is already taken care of. so your final code looks like :
function doubleChar(str) {
var splt = str.split("");
var rpt=''
for(var i=0;i<splt.length;i++){
rpt += splt[i].repeat(2);
}
return rpt
}
console.log(doubleChar("hello"));
The big problem I see here is that rpt is within the loop. So, the for loop will return "hh", then "ee", so on so forth. In practice, the function stops after returning a value so this would currently return 'hh'. To solve this, you need to move the variable outside of the for loop. Something like this:
var result = ""
for(var i=0;i<splt.length-1;i++){
result = result + splt[i] + splt[i]
}
return result;
Then you could console.log the result.
Answers above/below a great and correct. However, I'd like to answer using almost exactly the same code as in the question as it may be more helpful if you've just started learning JS.
You get "join is not a function" error because .repeat(n) returns a string and strings do not have such a method.
Then, you need to stop return inside of a loop as it actually returns from the whole function so you will only get the first letter doubled as a result. Instead, declare variable for storing result and concat it with a new doubled letter in loop. Return result in the end.
Here is the modified code:
function doubleChar(str) {
var splt = str.split("");
var result = ""; // add the var for future result
for(var i=0; i<splt.length; i++){
var rpt = splt[i].repeat(2); // this is string!
result += rpt; // concat string to current result
}
return result;
}
console.log(doubleChar("hello"));
The value of rpt is a string, and does not have a join function. You also immediately return inside the for loop, which will do that in the first iteration.
You can split, map and join instead:
const re = "hello".split('').map(s => s + s).join('');
console.log(re);
Your declaration of rpt is should be on the top, and the return should be outside your for loop. Other than that, its fine.
function doubleChar(str) {
var splt = str.split("");
var rpt = "";
for (var i = 0; i < splt.length; i++) {
rpt = rpt + splt[i].repeat(2);
}
return rpt;
}
console.log(doubleChar("hello"));
var rpt= splt[i].repeat(2);
return rpt.join('');
It is choking on this line because rpt is not an array and you're calling join() on it. Instead, just replace the original array item with the new double item.
function doubleChar(str) {
var splt = str.split("");
for(var i=0;i<splt.length-1;i++){
splt[i]= splt[i].repeat(2);
}
return splt.join('');
}
console.log(doubleChar("hello"));
all in one line...
str = "hello";
var dbl = str.split("").map(el => el.repeat(2)).join("")
console.log(dbl)
Now here is the same thing, but like your example, we'll only double up single letters
str = "hello", lastletter='';
var dbl = str.split("").map(el => {
if (el != lastletter) {
el = el.repeat(2)
lastletter = el.split("")[0]
return el
}
}).join("")
console.log(dbl)
I think most of the solutions here is hello->hheelllloo but you wanted like -> hheelloo
So assuming you only want to repeat single char. I'm giving the solution which also is the same code that you gave.
function doubleChar(str) {
var splt = str.split("");
var rpt="";
for(var i=0;i<splt.length;i++)
rpt+=((splt[i+1]&&splt[i]==splt[i+1]?splt[i++]:splt[i]).repeat(2));
return rpt;
}
console.log(doubleChar("hello"));
May be the line inside for loop seems complex but if you break this, it will be very simple
(splt[i+1]&&splt[i]==splt[i+1]) here I'm checking if the next char exist and equal to the current char, if so then take the current and skip the next char else take the current and don't skip the next char, and after this just repeating the char which we took.
rpt+=((splt[i+1]&&splt[i]==splt[i+1]?splt[i++]:splt[i]).repeat(2));
Hope you got this

Issue with my var getting undefined

I am trying to create a reverse function to the String type in javascript. My code is like
String.prototype.reverse = function () {
var s = "";
for(var i=this.length;i>=0;i--){
s+=this[i];
}
return s;
}
When I try to use it on for example like "test".reverse();
instead of giving "tset" it's giving "undefinedtset"
I am setting the variable like var s = ""; inside the function, still undefined is coming. Why is it so?
You just need to change var i=this.length to var i=this.length-1, because an array starts at position 0 :
String.prototype.reverse = function () {
var s = "";
for(var i=this.length-1;i>=0;i--){
s+=this[i];
}
return s;
}
this.length gives you 4 (4 letters in test word) and you start iterating from 4 to 0.
The problem is that nothing exists under 4 index (your letters are stored in 0-3 positions).
Try with:
for (var i = this.length - 1; i >= 0; i--) {
s += this[i];
}
The reason why your code isn't working has been answered by the others already, but if you want a shorter version of the reverse, you can do it like this:
String.prototype.reverse = function(){
return this.split('').reverse().join('');
}
console.log('Hello World'.reverse())

JS: Reversing a string using nested loop does not work

I have written a function called reverseStr that takes in a string as a parameter and returns the string but with the characters in reverse.
For example: reverseStr('bootcamp'); => 'pmactoob'
Following is my program:
function reverseStr(str)
{
var splitStr = str.split("");
console.log(splitStr);
var reverseString = [];
for(var i = 0; i <= splitStr.length -1 ; i++)
{
for(var j = splitStr.length - 1; j >= 0; j--)
{
reverseString[i] = splitStr[j]
}
}
return reverseString.toString().replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
If I run the function reverseStr("bootcamp") it returns bbbbbbbb.
Does anyone see a problem with the code?
Note: I DONOT WANT TO USE REVERSE() BUILT-IN FUNCTION
However, I found success with the following code but still need an answer to my initial question
function reverseStr(str)
{
var splitStr = str.split("");
reverseStr = "";
for(var i = splitStr.length - 1; i >= 0 ; i = i - 1)
{
reverseStr += splitStr[i];
}
return reverseStr;
}
You don't need to double-iterate through the characters, i.e., do not need to nest for loops. Iterate once and grab the chars in reverse order, like this:
function reverseStr(str)
{
var splitStr = str.split("");
console.log(splitStr);
var reverseString = [];
for(var i = 0, j=splitStr.length-1; i <= splitStr.length -1 ; i++, j--)
{
reverseString[i] = splitStr[j]
}
return reverseString.toString().replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
You can see that here the loop goes on for as long as i <= splitStr.length -1,ie, length of the string. This is sufficient to get the mirroring character (i versus Array.length-i).
Here is a working snippet to demo:
var reverseStr = function(str) {
let result = String();
for(let i = str.length-1; i >= 0; i--) {
result += str.charAt(i);
}
return result.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
$('button').click(function() {
$('.result').text(reverseStr($('#str').val()));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="str">
<button>Reverse it</button>
<div class="result"></div>
Perhaps a more elegant way to achieve the same (apart from Array.prototype.reverse()) would be to use String.prototype.chatAt(). This would avoid two conversions to and from an array, and also save you one variable. Granted, the code is much shorter and more obvious in what it is doing.
var reverseStr = function(str) {
let result = String(); // An empty string to store the result
for(let i = str.length-1; i >= 0; i--) { // Iterate backwards thru the chars and add to the result string
result += str.charAt(i);
}
return result.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, ''); // Original return method of the author
}
$('button').click(function() {
$('.result').text(reverseStr($('#str').val()));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="str">
<button>Reverse it</button>
<div class="result"></div>
The problem is that your nested for loop runs its whole course before it returns to the outer for loop. So, it just repeats one character the amount of times equal to the length. Instead of having another for loop, just add a simple counter for j like j++ inside your outer for loop and use that value with the i value.
To the original poster, consider this:
If you know the length of the original string, you therefore know the offset of that last position within the original string.
Iterate through the original string in reverse order, appending the current position's value to a new string. The new string would be the reverse of the original.
Aydin's example is essentially correct. Here's my very similar version, with comments:
function reverseString(inputString) {
// create a new empty string
var newString = "";
// iterate through the characters of the string in reverse order,
// appending to the new string
for (var i = inputString.length - 1; i >= 0; i--) {
newString += inputString[i];
}
return newString;
}
console.log(reverseString('bootcamp'));

How to compare Palindromes

Not sure what i did wrong. I'm trying to compare 2 strings to see if they are Palindromes
function palindrome(str) {
var rem = str.replace(/\s/g, "");
var a = rem.split("");
var b = a.reverse();
for(var i = 0; i < rem.length; i++){
if (b[i] == a[i]){
return true;
}
return false;
}
}
palindrome("not a doctor"); //this should show false, but it's showing true
The reverse method transposes the elements of the calling array object in place, mutating the array, and returning a reference to the array.
Source
That's why you get true. Seems your a and b variables point to the same object.
By the way, your approach seems somewhat flawed as others have pointed out bellow. So, a better version of solution to your task could be (not properly tested):
function isPalindrome(input) {
var str = input.replace(/\s/g, "").toLowerCase();
var left = 0, right = str.length - 1;
while( left <= right) {
if(str[left] !== str[right]) return false;
left++; right--;
}
return true;
}
console.log(isPalindrome("your string")); // false
console.log(isPalindrome("Drawn onward")); //true
The idea is that you compare the corresponding symbols on both ends of your modified (without spaces and lowercased) string. If they don't match at some point, so this is not a palindrome.
There are a few problems with your code.
Problem 1: You are using reverse method which mutate the original array (See the docs on reverse). So variables a and b would have the same value, that is the reversed string of the original array. What you can do instead is create a fresh new array and assign it to the variable b like so:
var b = [].concat(a).reverse();
Problem 2: You forgot to check ALL of the letters in the string. You are returning your function way too early. For example, for the input string 'aada', which is not a palindrome it will return true. This is because, your function exits as soon as evaluates the similarity of the first string of both arrays. To fix this you could do something like this:
function palindrome(str) {
var rem = str.replace(/\s/g, "");
var a = rem.split("");
var b = [].concat(a).reverse();
for(var i = 0; i < rem.length; i++){
if (b[i] !== a[i]){
return false;
}
}
return true
}
You can even further optimise your function like this:
function palindrome(str) {
const len = str.length;
const halfLen = len/2;
for (let i = 0; i < halfLen; i++) {
if (str[i] !== str[len - 1 - i]) return false;
}
return true;
}
Palindrome strings read the same backwards and forwards, So you can make a comparison of the first and the last, second to second last etc until you reach the middle character.
Hope this helps.
As others have said, your a and b points to same object, so you need to clone it first.
Also you must not return true immediately, better way is to check for inequality and return true after the whole cycle ends.
function palindrome(str) {
var rem = str.replace(/\s/g, "");
var a = rem.split("");
var b = a.slice().reverse();
console.log(a, b);
for(var i = 0; i < rem.length; i++){
if (b[i] != a[i]){
return false;
}
}
return true;
}
console.log(palindrome("lol 1"));
Your code had two problems.
As noted by #curveball, your a and b variables are references to the same objects, as reverse modifies the original array.
Additionally, you are returning true as soon as the first element in the a array is equal to the first element of the b array. You must return false as soon as one element is different from another. But can only return true after comparing all the elements in the array.
function palindrome(str) {
var rem = str.replace(/\s/g, "");
var a = rem.split("");
var b = a.slice().reverse();
for(var i = 0; i < rem.length; i++){
if (b[i] !== a[i]){
return false;
}
}
return true;
}
palindrome("not a doctor");
Additionally, an alternative (and typical) algorithm for checking whether a string is a palindrome would be to compare (after removing blanks) first position to last one, second position to second from the end, etc. That way it is not necessary to clone (and reverse) the data.

Splice NOT removing certain characters

I'm working on some codewars problems and I came to this 'remove noise thing', I guess the point is to escape backslash \ and use replace method, which was easy. But I didn't want to use replace, instead I found myself in trouble trying to remove items with splice method.
Funny thing is, when I debug in Chrome dev tools, step by step I see items get removed, but console.log spits out certain characters($/路|陋l) problematic to remove, and at the end gets returned and join with those characters. Why is that?
function removeNoise(str) {
var base = "%$&/#路#|潞\陋";
var arr = str.split('');
for(var i = 0; i < arr.length; i++) {
var item = arr[i];
var condition = base.indexOf(item);
if(condition + 1) {
//works like a charm
//arr[i] = '';
arr.splice(i,1);
//this thing wont work
//when debugging it removes the items from the array
//console log print no removing
}
}
return arr.join('');
}
removeNoise('he%$&/#路#|潞\陋\llo'); //=> $/路|陋llo
You're using splice to remove entries from your array, but you're then incrementing i for the next loop. If you remove the entry at index 5 from a 10-entry array, what was the entry at index 6 is now at index 5 (of what's now a 9-entry array), so you don't want to increment your index.
The solution is to use a while loop and only update i if you don't splice:
function removeNoise(str) {
var base = "%$&/#路#|潞\陋";
var arr = str.split('');
var i = 0;
while (i < arr.length) {
var item = arr[i];
var condition = base.indexOf(item);
if (condition + 1) {
// Remove this entry, reuse same value for 'i'
arr.splice(i,1);
} else {
// Don't remove this entry, move to next
++i;
}
}
return arr.join('');
}
var result = removeNoise('he%$&/#路#|潞\陋\llo');
var pre = document.createElement('pre');
pre.appendChild(
document.createTextNode(result)
);
document.body.appendChild(pre);
You're removing characters from your array. This will throw your indexer variable i out of sync with the characters you want to test. Easy way to fix is to start at the end of the array working your way to the beginning.
Change your for loop to this.
for(var i = arr.length -; i <= 0; i--) {
function removeNoise(str) {
var base = "%$&/#路#|潞\陋";
var arr = str.split('');
for(var i = arr.length - 1; i <= 0 ; i--) {
var item = arr[i];
if(base.indexOf(item) >= 0) {
//remove the offending character
arr.splice(i,1);
}
}
return arr.join('');
}
removeNoise('he%$&/#路#|潞\陋\llo'); //=> $/路|陋llo

Categories