syntax for javascript reverse function - javascript

hey guys I understand that the following will work for reversing a string passed to the function:
function reverseString(str) {
return str.split('').reverse().join('');
}
reverseString("hello");
however can someone help me understand why the following won't work?
function reverseString(str) {
str.split(' ');
str.reverse();
str.join(' ');
return str;
}

Those functions don't modify the string; strings are immutable. The functions return new values.
So, a statement like
str.split('');
is a valid statement, but it has no net effect because the returned array is ignored. In the first example you quoted, the returned values are used as object contexts from which the subsequent functions are accessed and called. The return statement there returns the result of the last function call in the chain (the .join() call).

Try using var , if expected result is to re-define str , set using str = /*new value */
function reverseString(str) {
var copy = str.split("");
copy.reverse();
str = copy.join("");
return str;
}
console.log(reverseString("hello"))

Firstly, strings are immutable, you can create new required string, using methods like the first one to return value by operating/invoking methods.
The first function calls methods in chain. Meaning, the return value of one function (object/reference types only) to invoke its method to compute new result.
str.split('').reverse().join('');
Here, split returns array and array's reverse method reverses contents in array (index) and finally join method joins the array elements with ' ' as separator.
whereas in second function its just a sequential call of statements. I guess in str.join(' '); there is no function called join in string prototype.

The method calls are chained so that each method uses the return value from the previous. You can do the same in separate statements if you keep the return value so that you can use it in the next statement:
function reverseString(str) {
var arr = str.split('');
arr = arr.reverse();
var result = arr.join('');
return result;
}
console.log(reverseString("hello"));
Note also that there is a difference between split('') and split(' '). The first one splits between each character while the second one splits at space characters.

Related

Capitalize the first letter of each word using

I'm doing a class on javascript this semester, and one of this week's exercises was to take a string of words, and capitalize the first letter of each word.
I did that using .map(), the code is here :
let t1 = "hello how are you doing".split(" ");
let t2 = t1.map(function(word) {
return word[0].toUpperCase() + word.slice(1);
});
console.log(t2.join(" "));
And it works perfectly fine. However, I was wondering why, when I try with forEach(), I can't make it work. Here is my code :
let t1 = "hello how are you doing".split(" ");
t1.forEach(function(word) {
word[0] = word[0].toUpperCase();
})
console.log(t1.join(" "));
My understanding of forEach() is that it cycles through every element of the table, much like a simple for loop. So then shouldn't my code take the first letter of each word, and replace it with the same letter, to which toUpperCase() is applied?
edit : I already know how to capitalize the first letter of each word, I was just asking about the different methods
First, string in JS is immutable.
var str = 'hello World';
str[0] = 'H';
console.log(str)
So word[0] = will not have any effect.
Second, even if it was, you are updating a value of an argument variable and not value in array.
var a = [1, 2, 3];
a.forEach(function(n) {
n = n * 2;
});
console.log(a)
As per discussion with #deceze, this point is not accurate.
If a string was mutable, that would have worked just fine. Your "Second" doesn't really apply. – deceze
#deceze Objects are assigned using reference, so it will have the effect. Primitive values are assigned using value. So n in my understanding will always be a copy of item in array. Any manipulation relating to it should not affect the item in array. And string being a primitive value, I mentioned it. Also, I can't think of any variable that has property and is of primitive type. If you have any idea please let me know. Would be glad to learn. :-) – Rajesh
Sure, you're right about that. That's why I'm saying if it was mutable in the first place… Since it's not, the point is moot either way. – deceze
To get the desired effect, you will have to override value in array.
let t1 = "hello how are you doing".split(" ");
t1.forEach(function(word, index) {
t1[index] = word[0].toUpperCase() + word.substring(1);
})
console.log(t1.join(" "));
Reference:
Are JavaScript strings immutable? Do I need a "string builder" in JavaScript?
let word = 'foo';
word[0] = 'F';
console.log(word);
The modification of word doesn't take because strings are immutable. You can't change a single character inside a string.
For character access using bracket notation, attempting to delete or assign a value to these properties will not succeed. The properties involved are neither writable nor configurable.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
So then shouldn't my code take the first letter of each word, and
replace it with the same letter, to which toUpperCase() is applied?
Because word is a primitive value hence when you set new value to word, it doesn't carry the reference back to the array.
However, if parameter of forEach is not a primitive value, then the original one gets mutated, see the demo below
var arr = [[1,2,3],[4,5,6],[7,8,9]];
arr.forEach(function(item){
item.push(1);
})
console.log(arr);

preg_match_all to javascript

Can anyone help converting this PHP regex pattern to a JavaScript compatible one?
PHP
preg_match_all('/(?ims)([a-z0-9\s\.\:#_\-#,]+)\{([^\}]*)\}/', $data, $matches);
Javascript
matches=data.match(/(?ims)([a-z0-9\s\.\:#_\-#,]+)\{([^\}]*)\}/);
Thanks
To mimic the PHP output, you need to look at more than only the regular expression. For a single match, the JavaScript match method will do the trick, but for multiple matches it will no longer return the captured groups. In fact, there is no out-of-the-box statement in JavaScript that is equivalent to preg_match_all.
The method that comes closest is regex.exec, being the only method that can both return the captured groups and multiple matches. But it does not return all the matches in one go. Instead you need to iterate over them, for instance like this:
for (matches = []; result = regex.exec(data); matches.push(result));
Now the regular expression needs also some adjustments:
In Javascript the modifiers (ims) cannot be specified like you have it, they must be specified at the end, after the closing slash. Note that in PHP you can do the same.
Secondly, Javascript has no support for the s modifier. But in your case this is not a problem, as your regular expression does not rely on it -- you would get the same results without that modifier.
In order for the exec method to return multiple matches, the regular expression must use the g modifier, which is not needed nor allowed in PHP's preg_match_all -- the _all in the method name already takes care of that.
So, in JavaScript, the regular expression will be defined like this:
var regex = /([a-z0-9\s\.\:#_\-#,]+)\{([^\}]*)\}/gim;
Finally, the matches are returned in a different format than in PHP. Let's say the data is "Alpha{78} Beta{333}", then PHP will return:
[["Alpha{78}"," Beta{333}"],["Alpha"," Beta"],["78","333"]]
But the above JavaScript code returns that data in a transposed way (rows and columns are swapped):
[["Alpha{78}","Alpha","78"],[" Beta{333}"," Beta","333"]]
So, if you also want that to be the same, you need to transpose that array. Here is a generic transpose function you could use for that:
function transpose(a) {
return a[0].map(function (val, c) {
return a.map(function (r) {
return r[c];
});
});
}
So putting it all together, this will do the job:
function transpose(a) {
return a[0].map(function (val, c) {
return a.map(function (r) {
return r[c];
});
});
}
// test data:
var data = "Alpha{78} Beta{333}";
var regex = /([a-z0-9\s\.\:#_\-#,]+)\{([^\}]*)\}/gim;
// collect all matches in array
for (var matches = []; result = regex.exec(data); matches.push(result));
// reorganise the array to mimic PHP output:
matches = transpose(matches);
console.log(JSON.stringify(matches));
// for this snippet only:
document.write(JSON.stringify(matches));
Output:
[["Alpha{78}"," Beta{333}"],["Alpha"," Beta"],["78","333"]]

Return statement in javascript doesn't exit the function?

I wrote a simple function to sort objects not expecting it to work but it does:
function sortObjs(objArr,field) {
objArr.sort(
function(a,b) {
if( isNaN(a[field]) ) {
return a[field].localeCompare(b[field]);
} else {
return parseFloat(a[field]) - parseFloat(b[field])
}
}
);
return objArr;
}
When I call this function I get my sorted objects without issue. But I was not expecting it to work because I thought the first two return statements would exit the function before it got to the last statement: return objArr.
You have a nested function. The first two returns will exit the inner function, while the last one will exit the outer one.
EDIT:
You can think of function returns as "replacing" the function with the returned value. For example:
var i = getSum(1, 3);
function getSum(a, b) {
return a + b;
}
The function getSum returns the sum of a and b. The line var i = getSum(1, 3) will execute the lines of code contained in the function with a = 1 and b = 3. The value that is returned "replaces" the function call. So now the line of code looks like var i = 4;. Although this is not exactly how it works, it's a good way to conceptualize it. This is a special case because you aren't actually running the inner method here, you're passing it as a variable.
Let me know if you have any more questions!
To understand why the inner function's return statements would not have an effect on the return statement in the outer scope, you need to understand how the Array.prototype.sort() function works.
The function arr.sort([compareFunction]), takes a function as a parameter.
compareFunction
Optional. Specifies a function that defines the sort order.
If omitted, the array is sorted according to each character's Unicode code point value,
according to the string conversion of each element.
The logic you write inside the compareFunction gets executed when
the java script engine tries to compare two elements during its
comparison operation.
Hence for each comparison that it makes, the function would return a
value, based on which the elements would be ordered.
This implies that the compareFunction that we pass on as a parameter
would be used to just obtain a value based on which two elements can
be compared and not exit the sort operation, leave alone exiting the
outer function.
Having said this, the code return objArr;, takes no effect, since the array would be sorted in place.

How come this function isn't reassigning the variable?

I am doing a simple javascript problem where I have to pass an array through a function and have the array reassigned a different value. How come when I pass through an array (or even any variable) I have to specifically reassign the array in order for it to change? Can't I just use the code in the function to use the parameter to do that for me? Here's my code:
<script>
var str = 'this is my sentence';
//Write a function called reverse that takes is given str as it's only argument and returns that string after it's been reversed
function reverse(x) {
x = x.split('').reverse().join('');
return x;
}
//returns with the text reversed, but str is still 'this is my sentence' and not the reversed version
</script>
You have to actually call the reverse function. Your code works once you add str = reverse(str);
<script>
var str = 'this is my sentence';
//Write a function called reverse that takes is given str as it's only argument and returns that string after it's been reversed
function reverse(x) {
x = x.split('').reverse().join('');
return x;
}
str = reverse(str); //Call the function
window.alert(str); //show an alert box to view reversed string
</script>
EDIT
It seems the brunt of his question is [Why do] I have to specifically reassign the array in order for it to change?.
The argument is a primitive and with primitives, javascript passes by value. Meaning that the called functions' parameter will be a copy of the callers' passed argument. It is not the same item.
The alternative would be pass by reference in which case the called functions' parameter will be the same object as the caller's passed argument. In this case, changes occurring inside the function on the object passed as a parameter will be 'available' outside the function - because it's the same object. This is how Javascript passes objects.
In Javascript, a string can be either an object or a primitive depending on how you create it:
var str = "I'm a String primitive"; //This is a primitive
var str = new String("I'm a String object"); //this is an object

$.each function to add return to an external variable

I have an Array of Strings, which i process with this function:
$.each(lines, processLine);
processLine function returns another string, but i need to combine the strings into one result. The main problem is that i don't want the processLine function to refer to the external variable (named css), it just has to return the result, and do the combination externally. So here's what i did:
var css = '';
css += $.each(lines, processLine);
But css variable ends up with the combinations of the original Arrays elements (not processed), don't know why...
$.each() iterates, $.map() projects. Since you want to project values from your lines, you should use $.map():
var css = $.map(lines, processLine).join("");
The function passed to $.map() is invoked for each item in the array with two arguments: the item itself and its index. Since processLine() takes a line as its first and only argument, we can pass that function directly instead of using an anonymous function as an intermediate.
From there, join() will build a string from our projected array. Passing the empty string as a separator results in simple concatenation.
EDIT: If processLine() does not take a single line argument, then my reasoning above is incorrect and you have to write something like:
var css = $.map(lines, function(line, index) {
return processLine(index, line);
}).join("");
Well you can implement a function like this:
function processLines(lines) {
var resultCss = '';
$.each (lines, function() { resultCss += processLine(this) });
return resultCss;
}
var css = processLines(yourLines);

Categories