Why doesn't it recognize join() as a function? - javascript

I'm trying to capitalize every first letter of the given string, however every time I run the code I get the following error:
TypeError: val[i].charAt(...).toUpperCase(...).join is not a function
function titleCase(str) {
var strArry = str.toLowerCase().split(' ');
strArry.map(function (val) {
for (var i = 0; i < val.length; i++) {
return val[i].charAt(0).toUpperCase().join(' ') + strArry[i].splice(1);
};
});
}
titleCase("I'm a little tea pot");

String.protoype.toUpperCase() returns a string, and Array.prototype.join() is on the Array prototype, not the string.
You probably want something like this...
return val[i].charAt(0).toUpperCase() + val[i].slice(1);
...or possibly even better (at least shorter)...
function titleCase(str) {
return str.replace(/\b[a-z]/g, function(match) { return match.toUpperCase(); });
}
Here I am using a regex to match the first lowercase letter after a word boundary, and then using a custom replacer to return it uppercased.
If you supported more than latin, then use a Unicode range to select the characters.

toUpperCase returns a String and join is not a method on that prototype.
If you run through your code and put a typeof check in before mucking with the string, you can see:
function titleCase(str) {
var strArry = str.toLowerCase().split(' ');
strArry.map(function (val) {
for (var i = 0; i < val.length; i++) {
var temp = val[i].charAt(0).toUpperCase();
console.log(typeof temp);
return temp;
};
});
}
titleCase("I'm a little tea pot");
You need to join the Array after you've mapped it to produce the final combined value.

I propose this short piece of code which works well :
var titleCase = (str) => str.split(" ").map(el => el[0].toUpperCase().concat(el.substr(1))).join(" ");
console.log(titleCase("I'm a little tea pot"));

Figured it out with a bit a research and found that using val worked with me trying to use mpa()
function titleCase(str) {
var strArry = str.toLowerCase().split(' ');
var convert = strArry.map(function(val) {
return val.replace(val.charAt(0), val.charAt(0).toUpperCase());
});
return convert.join(' ');
}
titleCase("I'm a little tea pot");

Im am not Familiar with Javascript, which is why I fo not know if it makes a difference between char and string.
I am quite sure you meant do an entirely different thing, namely return a string joined from capitalized letters. What you are (trying) to do here however is returning the result of your expression (val[i].andsoonandsoforth) after the first cycle of your for loop.
The reason why the expression doesn't work will be that join(string) is usually called on arrays of strings or characters. You are calling it on a single character however!
The solution would be to first split uf the string into characters, capitalize them, store them into an array, call join on that array and return the thing afterwards.
Or just use the likely existent builtin capitalize functions on strings.

Related

a bit clarafication on using spread and string manipulation, foreach loop

so I've wrote this function, i want to uppercase the vowels and lowercase every other letter,
problem the end result ends with the same string, I'm new to spread and for-each,
after i spread a string does it become an array?
when i manipulate letters does it suppose to become a string again with the manipulations or do i need to join it? why aren't the upper and lowercase functions don't work?
the function:
function upperCase(str) {
var vowels = "aeiou";
[...str].forEach(letter => {
if (vowels.includes(letter)) letter.toUpperCase();
letter.toLowerCase();
});
console.log(str);
}
You have several problems:
.toUpperCase and toLowerCase return the new value, they don't mutate the existing value (and strings are immutable anyway)
Even if they did mutate the existing value, they'd change the letter string in the array and not the original string
You didn't use else to toLowerCase always runs
You need to:
return a value
Use map to collect the values
Use join() to turn the array back into a string
Such:
function upperCase(str) {
const vowels = "aeiou";
const result =
[...str]
.map(
letter =>
(vowels.includes(letter))
? letter.toUpperCase()
: letter.toLowerCase()
).join("");
console.log(result);
}
upperCase("The quick brown fox jumps over the lazy dog");
You need to assign the result of your foreach to something.
function upperCase(str) {
var vowels = "aeiou";
[...str].forEach(letter => {
if (vowels.includes(letter)) letter.toUpperCase();
letter.toLowerCase();
});
console.log(str);
}
[...str] is creating an array, looping over it, preforming an action, but then not saving the resulting array to any variable at the end. You're also missing an else and/ or a return. I think a map also makes more sense in this case.
function upperCase(str) {
var vowels = "aeiou";
const result = [...str].map(letter => {
if (vowels.includes(letter)) return letter.toUpperCase();
return letter.toLowerCase();
});
console.log(result);
}
If you just want to manipulate a string you might want to use the replace function
const newString = str.toLowerCase().replace(/[a,e,i,o,u]/g, letter => letter.toUpperCase())
This first puts everything to lower case, and afterwards replaces all vowels (matching the regular expression) by their upper case versions.

Remove all consonants in a string before a vowel then add a character

I want to remove all consonants in a string before the occurrence of a vowel and then replace it with an 'r'.
This means that 'scooby' will become 'rooby', 'xylographer' will become 'rographer' and so on. This is the algorithm I came up with:
1. Check if input type is not a string.
2. Use a variable(newStr) to hold lowercase conversion and splitted word.
3. Declare a variable(arrWord) to hold the length of the array.
4. Another variable called regex to check if a string starts with a consonant
5. Variable newArr holds the final result.
6. Search through the array, if the string does not start with a consonant
join it and return it.
7. Else keep looking for where the first vowel occurs in the word.
8. When found, remove all characters(consonants) before the vowel occurence
and replace them with an r.
9. Join the array together.
I have been able to come up with this:
const scoobyDoo = str => {
if(typeof str !== 'string'){
return 'This function accepts strings only';
}
let newStr = str.toLowerCase().split('');
let arrWord = newStr.length;
let regex = /[aeiou]/gi;
for (let i = 0; i < arrWord; i++){
if (newStr[0].match(regex)) {
let nothing = newStr.join('');
return nothing;
}
else {
let vowelIndex = newStr.indexOf(str.match(regex)[0]);
newStr.splice(0, vowelIndex, 'r');
return newStr.join('');
}
}
}
console.log(scoobyDoo('scOoby'));
I tested out the program again by capitalizing the first vowel index and instead of 'rooby' I get 'rscooby'. Why is that so?
Can you once try with following code in your else and see the changes
else {
var vowelIndex = newStr.indexOf(str.match(regex)[0]);
newStr.splice(0, vowelIndex, 'r');
return newStr.join("");
}
Is it not much easier like this? Or am I missing something??
'xylographer'.replace(/^\s*[^aieou]+(?=\w)/i,function(m,o,s){return "r"})
//"rographer"
'scooby'.replace(/^\s*[^aieou]+(?=\w)/i,function(m,o,s){return "r"})
//"rooby"
you could just use one reg expression for the whole algorithm and no need to split your string no more.
regexp to use.
/^[^aouie, AOUIE]+(?=[aouie, AOUIE])/g
of course you can readjust regexp to suit you more but this will get your main requirement.
On the line immediately after the else statement, I just called .toLowerCase() on it and it was fixed:
let vowelIndex = newStr.indexOf(str.match(regex)[0].toLowerCase());
I like keeping my code simple and readable
function pattern(str){
var vowelIndex = str.indexOf(str.match(/[aeiou]/)); //returns index of first vowel in str
return "r" + str.slice(vowelIndex);
}
console.log(pattern('xylographer'));

How to generate easy anagrams preserving punctuation?

I'm writing the hint system for a quiz. The hints are to be anagrams of the answers. To make the anagrams easier, I keep the first and last letters the same.
var _ = require('underscore');
var easy = function(s) {
if (s.length <= 1) {
return s;
}
return s[0] + _.shuffle(s.slice(1, -1)).join("") + s.slice(-1);
};
For multiple word answers, I want to anagram each word separately. I wrote:
var peasy = function(s) {
return s.split(/\W/).map(easy).join(" ");
}
However this loses any punctuation in the answer (replacing it with a space). I'd like to keep the punctuation in its original position. How can I do that?
Here are three examples to test on:
console.log(peasy("mashed potatoes"));
console.log(peasy("computer-aided design"));
console.log(peasy("sophie's choice"));
My function peasy above fails the second and third examples because it loses hyphen and apostrophe.
Splitting by word separator does the trick:
var peasy = function(s) {
return s.split(/\b/).map(easy).join("");
}
Explanation:
"computer-aided design".split(/\b/) results in ["computer", "-", "aided", " ", "design"]. Then you shuffle each element with easy and join them, getting something like "ctemopur-adeid diegsn" back...
It's more simple to use String.prototype.replace instead of splitting:
you don't need to slice after the first and before the last letter.
the replacement occurs only on word characters (other characters stay untouched)
words with less than 4 characters are skipped.
it's shorter and doesn't need the easy function.
var _ = require('underscore');
var peasy = function(s) {
return s.replace(/\B\w{2,}\B/g, function (m) {
return _.shuffle(m).join('');
});
}

Javascript to capitalize the next char after " Mc"

Given a string like Marty Mcfly is there a regex or other one line solution to capitalize the 'f' so I get Marty McFly?
I can always count on the space between first and last and the first letter of the last name (i.e. the M) will always be caps.
I'm pretty open to just about any javascript, jquery, regex solution, I just need it to be short and sweet.
I've got a method that takes the string apart using indexOf and substring but I'm hoping theres a regex or something similar.
You can take advantage of the form of String.replace which takes a function as its second argument:
function fixMarty(s) {
return (""+s).replace(/Mc(.)/g, function(m, m1) {
return 'Mc' + m1.toUpperCase();
});
}
fixMarty('Marty Mcfly'); // => "Marty McFly"
fixMarty("Mcdonald's"); // => "McDonald's"
This is a perfect case for using a callback with .replace().
function fixMc(str) {
return(str.replace(/\bMc(\w)/, function(match, p1) {
return(match.slice(0, -1) + p1.toUpperCase());
}));
}
Here's a jsFiddle http://jsfiddle.net/jfriend00/Qbf8R/ where you can see it in action on a several different test cases.
By way of explanation for the how the callback works, the parameter match is the whole regex match, the parameter p1 is what the first parenthesized group matched and the callback returns what you want to replace the whole regex match with.
var text = 'Marty Mcfly';
text = text.replace(/Mc[a-z]/, function (k)
{
return 'Mc' + k[2].toUpperCase();
}
);
Use a combination of RegEx's exec method and String's replace method:
var name = 'Marty Mcfly',
pattern = /\bmc([a-z])/gi,
match = pattern.exec(name);
if (match) {
alert(name.replace(pattern, 'Mc' + match[1].toUpperCase()));
}
Here's a version that works with "Mac":
var name = 'Connor Macleod',
pattern = /\b(mc|mac)([a-z])/gi,
match = pattern.exec(name);
if (match) {
alert(name.replace(pattern, match[1] + match[2].toUpperCase()));
}
Here's the best I can do:
'Marty Mcfly'.replace(/ mc([a-z])/i, function (str, $1) {return " Mc" + $1.toUpperCase()})

Reversing a string in JavaScript

I'm trying to reverse an input string
var oneway = document.getElementById('input_field').value();
var backway = oneway.reverse();
but firebug is telling me that oneway.reverse() is not a function. Any ideas?
Thank you
reverse() is a method of array instances. It won't directly work on a string. You should first split the characters of the string into an array, reverse the array and then join back into a string:
var backway = oneway.split("").reverse().join("");
Update
The method above is only safe for "regular" strings. Please see comment by Mathias Bynens below and also his answer for a safe reverse method.
The following technique (or similar) is commonly used to reverse a string in JavaScript:
// Don’t use this!
var naiveReverse = function(string) {
return string.split('').reverse().join('');
}
In fact, all the answers posted so far are a variation of this pattern. However, there are some problems with this solution. For example:
naiveReverse('foo 𝌆 bar');
// → 'rab �� oof'
// Where did the `𝌆` symbol go? Whoops!
If you’re wondering why this happens, read up on JavaScript’s internal character encoding. (TL;DR: 𝌆 is an astral symbol, and JavaScript exposes it as two separate code units.)
But there’s more:
// To see which symbols are being used here, check:
// http://mothereff.in/js-escapes#1ma%C3%B1ana%20man%CC%83ana
naiveReverse('mañana mañana');
// → 'anãnam anañam'
// Wait, so now the tilde is applied to the `a` instead of the `n`? WAT.
A good string to test string reverse implementations is the following:
'foo 𝌆 bar mañana mañana'
Why? Because it contains an astral symbol (𝌆) (which are represented by surrogate pairs in JavaScript) and a combining mark (the ñ in the last mañana actually consists of two symbols: U+006E LATIN SMALL LETTER N and U+0303 COMBINING TILDE).
The order in which surrogate pairs appear cannot be reversed, else the astral symbol won’t show up anymore in the ‘reversed’ string. That’s why you saw those �� marks in the output for the previous example.
Combining marks always get applied to the previous symbol, so you have to treat both the main symbol (U+006E LATIN SMALL LETTER N) as the combining mark (U+0303 COMBINING TILDE) as a whole. Reversing their order will cause the combining mark to be paired with another symbol in the string. That’s why the example output had ã instead of ñ.
Hopefully, this explains why all the answers posted so far are wrong.
To answer your initial question — how to [properly] reverse a string in JavaScript —, I’ve written a small JavaScript library that is capable of Unicode-aware string reversal. It doesn’t have any of the issues I just mentioned. The library is called Esrever; its code is on GitHub, and it works in pretty much any JavaScript environment. It comes with a shell utility/binary, so you can easily reverse strings from your terminal if you want.
var input = 'foo 𝌆 bar mañana mañana';
esrever.reverse(input);
// → 'anañam anañam rab 𝌆 oof'
String.prototype.reverse = function () {
return this.split("").reverse().join("");
}
Inspired by the first result I got when I did a Google for javascript string reverse.
Google harder, bros. This is by Edd Mann.
function reverse (s) {
for (var i = s.length - 1, o = ''; i >= 0; o += s[i--]) { }
return o;
}
http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/
http://jsperf.com/string-reverse-function-performance
reverse is a function on an array and that is a string. You could explode the string into an array and then reverse it and then combine it back together though.
var str = '0123456789';
var rev_str = str.split('').reverse().join('');
// You could reverse a string without creating an array
String.prototype.reverse= function(){
var s= '', L= this.length;
while(L){
s+= this[--L];
}
return s;
}
var s1= 'the time has come, the walrus said, to speak of many things';
s1.reverse()
/*returned value: (String)
sgniht ynam fo kaeps ot, dias surlaw eht, emoc sah emit eht
*/
This is probably the way, acceptable for all browsers:
function reverse(s) {
var o = '';
for (var i = s.length - 1; i >= 0; i--)
o += s[i];
return o;
}
Call it like a charm:
reverse('your_string');
I like to share some notable implementations for string reverse.
split,reverse,join
const reverseString = (str) => str.split('') .reverse() .join('');
reduce
const reverseString =(str) => [...str].reduce((acc, cur) => cur + acc);
append last one by one
const reverseString = (str) => {
const ary = [];
for(let char of str) {
ary.unshift(char);
}
return ary.join('');
}
recursion
const reverseString =(str)=> (str === '') ? '' : reverseString(str.substr(1)) + str[0];
two pointer approach
const reverseString = (str) => {
const strArr = Array.from(str);
let start = 0;
let end = str.length - 1;
while (start <= end) {
const temp = strArr[start];
strArr[start] = strArr[end];
strArr[end] = temp;
start++;
end--;
}
return strArr.join("");
}
//Using reverse with split, reverse , join
function reverseString1(str) {
return str
.split('') // alternative [...str], Array.from(str)
.reverse() // alternative .sort(() => -1)
.join('');
}
// Using reduce
function reverseString2(str) {
return [...str].reduce((accumulator, current) => current + accumulator) // reduce from left to right
//alternative [...str].reduceRight((accumulator, current) => accumulator + current); // reduce right to left
}
// append to last one by one
function reverseString3(str){
const ary = [];
for(let char of str) {
ary.unshift(char);
}
return ary.join('');
}
// recursion with ternary with substr
function reverseString4(str) {
return (str === '') ? '' : reverseString4(str.substr(1)) + str[0];
}
// two pointer approach [less time complexity O(n)]
// front back chars exchanging
function reverseString5(str) {
const strArr = Array.from(str); // alternative [...str],str.split('')
let start = 0;
let end = str.length - 1;
while (start <= end) {
const temp = strArr[start];
strArr[start] = strArr[end];
strArr[end] = temp;
start++;
end--;
}
return strArr.join("");
}
console.log(reverseString1("Hello World"))
console.log(reverseString2("Hello World"))
console.log(reverseString3("Hello World"))
console.log(reverseString4("Hello World"))
console.log(reverseString5("Hello World"))
//=> dlroW olleH
Note:
Built-in method works well for ASCII inputs, not unicode things.. so use spread operation inspite of split. Check out split vs spread implementation
Extra:
In-Place string reverse is not possible in JS. Check out in-place reverse
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("#stringInput").keyup(function () {
debugger;
var string = $("#stringInput").val();
var stringArray = [];
sInput = string.toString();
for (var i = 0, len = sInput.length; i < len; i++) {
stringArray.push(sInput.charAt(i));
}
stringArray.reverse();
str = stringArray.join('');
document.getElementById("stringOutput").value = str;
});
$("button").click(function () {
debugger;
$("#myForm").toggle();
});
});
</script>
</head>
<body>
<div>
<form name="myForm" id="myForm">
<table>
<tr>
<td>Insert Elements :</td>
<td><input type="text" name="stringInput" id="stringInput"/></td>
<td>Output :</td>
<td><input type="text" id="stringOutput" name="stringOutput" readonly="true" /></td>
</tr>
</table>
</form>
<button>Show/Hide</button>
</div>
</body>
</html>
Reverse String using function parameter with error handling :
function reverseString(s)
{
try
{
console.log(s.split("").reverse().join(""));
}
catch(e)
{
console.log(e.message);
console.log(s);
}
}
I think you'll find that in fact reverse() isn't a function in jQuery. Incidentally, jQuery is really good at manipulating your DOM, but isn't really for string manipulation as such (although you can probably get plugins/write your own) to do this.
The best way I've found to reverse a string in javascript is to do the following:
String.prototype.reverse = function(){
splitext = this.split("");
revertext = splitext.reverse();
reversed = revertext.join("");
return reversed;
}
Found at: http://www.bytemycode.com/snippets/snippet/400/
I think you'll find that if you pop the above into your code somewhere, your call to .reverse() should work :)
Mathias Bynens, your code works grate, thanks a lot!
I convert your code to a function, in this way users are able to copy it from here.
Thanks!
//The function reverse a string, JavaScript’s has internal character encoding so we are
//unable to reverse the string in the "easy ways". For example the TL;DR: 𝌆 is an astral
//symbol, and JavaScript exposes it as two separate code units.
function ReverseString(string){
//-
var regexSymbolWithCombiningMarks = /([\0-\u02FF\u0370-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uDC00-\uFE1F\uFE30-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF])([\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]+)/g;
var regexSurrogatePair = /([\uD800-\uDBFF])([\uDC00-\uDFFF])/g;
//-
//Step 1: deal with combining marks and astral symbols (surrogate pairs)
string = string
//Swap symbols with their combining marks so the combining marks go first
.replace(regexSymbolWithCombiningMarks, function($0, $1, $2) {
return reverse($2) + $1;
})
// Swap high and low surrogates so the low surrogates go first
.replace(regexSurrogatePair, '$2$1');
// Step 2: reverse the code units in the string
var result = '';
var index = string.length;
while (index--) {
result += string.charAt(index);
}
//Return value
return result;
}
This reverse prototype function is implemented using "this".
If you see log console of "this", it will generate the array, and it has length property.
So that it!!! Just use reverse "for-loop" as shown in the code snippet.
String.prototype.reverse = function () {
console.log(this);
var result = "";
var len = this.length;
for (i = (len-1); i >= 0 ; i--) {
result += this[i];
}
return result;
};
alert("elahnu jaknap".reverse());
Use this simple method to reverse the words of a string at its position
function fun(str){
var arr1=str.split(' ');
console.log(arr1);
var strings='',rever='';
for(var i=0;i<arr1.length;i++)
{
strings=arr1[i].split('');
rever+=strings.reverse().join('')+' ';
}
console.log(rever.split(' '));
console.log(rever.trim());
};
fun('javascript is fun');
If it's necessary to revert the string, but return the original value of the error:
function reverseString(s) {
let valuePrintS;
try {
valuePrintS = s.split("").reverse().join("");
} catch {
console.log("s.split is not a function");
valuePrintS = s;
} finally {
console.log(valuePrintS);
}
}
I believe most performant solution with reduce like in https://stackoverflow.com/a/68978553/5018572 post
function reverse(str) {
return str.split("").reduce((final, letter) => letter + final);
}
console.log(reverse("Armaggedon"));
This is how I always do;
var rev = Array.prototype.reduce.call("Hello World",(p,c) => c+p);
console.log(rev);
Some people do it like [].prototype.redu... but that would be creating an array for no reason. Instead use the Array constructor.
Also some people ask why Array.prototype.reverse.call("Hello World") wouldn't work. It's so because .reverse() attempts to reverse the subject array in place and with immutable values in JS such as a String you can not do that.
String.prototype.strReverse = function() {
var newstring = "";
for (var s=0; s < this.length; s++) {
newstring = this.charAt(s) + newstring;
}
return newstring;
};

Categories

Resources