How can I dynamically use string.replace? - javascript

wordsArray = ['guy', 'like', 'sweet', 'potatoes']; //so on and so forth
string = "I am a **NOUN** and I **VERB** **ADJECTIVE** **NOUN**.";
DELIMITER = "**";
for (var i = 0; i < wordsArray.length; i++)
{
string.replace(DELIMITER, wordsArray[i]);
}
Hi, this is a simplified version of my code. I'm creating a mad lib, and the length of wordsArray will always be equal to the number of fill in the blanks. The problem with my current code is that in the for loop, it will replace every **. The thing is, I want to replace the entire thing, like **NOUN**, not just **. But since whatever is in between ** ** won't always be the same, string.replace() won't exactly work. Can Anyone suggest me an edit that could replace all the part of speeches but still eventually return string as a, well, block of proper text?

You can do it using string.match by catching all those **<STRINGS>** first:
var wordsArray = ['guy', 'like', 'sweet', 'potatoes'];
var string = "I am a **NOUN** and I **VERB-** **ADJECTIVE** **NOUN**.";
var DELIMITER = "**";
var newString = string; // copy the string
var stringArray = string.match(/(\*\*[A-Za-z-]+\*\*)/g); // array of all **<STRINGS>**
for (var i = 0; i < wordsArray.length; i++) {
newString = newString.replace(stringArray[i], wordsArray[i]);
}
console.log(newString);

You can bind your array to the replacer and call replace on your string once, I think it is much simpler:
"I am a **NOUN** and I **VERB** **ADJECTIVE** **NOUN**.".replace(/(\*\*\w+\*\*)/gi,(function(){
this._currentIndex = this._currentIndex || 0;
return this[this._currentIndex++];
}).bind(['guy', 'like', 'sweet', 'potatoes']));
//"I am a guy and I like sweet potatoes."

Using reduce:
const string = "I am a **NOUN** and I **VERB** **ADJECTIVE** **NOUN**.";
const newString = ['guy', 'like', 'sweet', 'potatoes'].reduce(
(theString, replacement) => theString.replace(/\*{2}\w+\*{2}/, replacement),
string
)

Related

`join()` and multidimensional arrays Javascript

I have this code:
var arr = str.split(' ');
for(var i=0, l=arr.length; i<l; i++) {
arr[i].split('');
arr[i][0].toUpperCase();
almost =arr[i].join('');
}
It returns the error "arr[i].join is not a function". I assume I have something wrong with the data types but I have no idea how to fix it.
Here, I think this is what you're looking for:
var str = 'This is a test string';
var arr = str.split(' ');
for(var i=0, l=arr.length; i<l; i++) {
var word = arr[i].split('');
word[0] = word[0].toUpperCase();
arr[i] = word.join('');
}
console.log(arr.join(' '));
JSFiddle: https://jsfiddle.net/6f9yoqtg/1/
It looks like others have explained why join does not work on a string. However, I noticed that your goal seems to be to uppercase every word in str. You can use the String#replace method for that, taking a function as the section parameter.
var string = 'word word words things amazing icons yup'
console.log(string)
string = string.replace(/(\S)(\S*)/g, function (_, first, rest) {
return first.toUpperCase() + rest
})
console.log(string)
When you use arr[i].split() you are not changing original element in array, so when you use arr[i].join('') you get error because arr[i] is still just a string and you can't use join on string. Instead you need to assign new value to that element so your code should look like this.
var arr = 'lorem ipsum'.split(' ');
for (var i = 0, l = arr.length; i < l; i++) {
arr[i] = arr[i].split('');
arr[i][0] = arr[i][0].toUpperCase();
arr[i] = arr[i].join('');
}
console.log(arr.join(' '))
Or instead you can store that value in variable, change it and then set it to value of current element in loop.
var arr = 'lorem ipsum'.split(' ');
for (var i = 0, l = arr.length; i < l; i++) {
var e = arr[i].split('');
e[0] = e[0].toUpperCase();
arr[i] = e.join('')
}
console.log(arr.join(' '))
With ES6, you could use destructuring ans rest syntax.
var str = 'This is a test string';
str = str.split(' ').map(([first, ...rest]) => [first.toUpperCase(), ...rest].join('')).join(' ');
console.log(str);
There are a few concepts that you need to consider here. if I'm not mistaken you are trying to create a function that will capitalize each first letter in a given string.
Start by simply creating a function that will take any string as a parameter using the variable str and then later manipulate it. Think of the function as a funnel something goes into it and then we have something that will come out the other end as an output. make sure you call the function later.
function capitalize(str) { };
capitalize(every firSt lettEr of the sentence);
Now inside the curly brackets is where the magic happens. we can use the .toLowerCase(), in case we might have capital letters some where along the string, and then use the .split() to split apart the letters at every empty space if there are many words in the string that we are trying to capitalize. Remember that after the split() you will no longer have a string but rather a string inside an array. Note that if you use 2 empty spaces in the split(' '), you will only capitalize the very first letter of the sentence.
function capitalize(str) { str = str.toLowerCase().split(' '); return str;}
//call function
capitalize(every firSt lettEr of the sentence);
//outputs ["every first letter of the sentence"]
then to iterate through each word in the array using a simple for loop like you have that will look like this:
for (var i=0; i<str.length; i++){}
in the curly brackets of the loop you will want to add a statement that will take the first letter of each word capitalize it then add the rest of the letters using splice(). it will go through each word in the array until there are non left, which is why we used the str.length. Lastly you will use the str.join() to put together the all the words in the array, that had a space between them, back into a string. it will look like this:
function titleCase(str) {
str = str.toLowerCase().split(' ');
for (var i = 0; i < str.length; i++) {
str[i] = str[i].charAt(0).toUpperCase() + str[i].slice(1);
}
return str.join(' ');
}
capitalize("every firSt lettEr of the sentence");
//output "Every First Letter Of The Sentence"
I hope that helped. if you need any help with the concepts don't be afraid to ask.

Using regular expression to split a string

I have a string which I need to separate correctly:
self.view.frame.size.height = 44
I need to get only view, frame, size, and height. And I need to do it with a regular expression.
So far I've tried a lot of variants, none of them are even close to what I want to get. And my code now looks like this:
var testString = 'self.view.frame.size.height = 44'
var re = new RegExp('\\.(.*)\\.', "g")
var array = re.exec(testString);
console.log('Array length is ' + array.length)
for (var i = 0; i < array.length; i++) {
console.log('<' + array[i] + ">");
}
And it doesn't work at all:
Array length is 2
<.view.frame.size.>
<view.frame.size>
I'm new at Javascript, so maybe I want the impossible, let me know.
Thanks.
In Javascript, executing a regexp with the g modifier doesn't return all the matches at once. You have to execute it repeatedly on the same input string, and each one returns the next match.
You also need to change the regexp so it only returns one word at a time. .* is greedy, so it returns the longest possible match, so it was returning all the words between the first and last .. [^.]* will match a sequence of non-dot characters, so it will just return one word. You can't include the second . in the regexp, because that will interfere with the repetition -- each repetition starts searching after the end of the previous match, and there's no beginning . after the ending . of the word. Also, there's no . after height, so the last word won't match it.
EDIT: I've changed the regexp to use \w* instead of [^.]*, because it was grabbing the whole height = 44 string instead of just height.
var testString = 'self.view.frame.size.height = 44';
var re = /\.(\w*)/g;
var array = [];
var result;
while (result = re.exec(testString)) {
array.push(result[1]);
}
console.log('Array length is ' + array.length)
for (var i = 0; i < array.length; i++) {
console.log('<' + array[i] + ">");
}
If you're sure that your data will be always in the same format you can use this:
function parse (string) {
return string.split(" = ").shift().split(".").splice(1);
}
In your context, split is a MUCH better option:
var str = "self.view.frame.size.height = 44";
var bits1 = str.split(" ")[0];
var bits2 = bits1.split(".");
bits2.shift(); // get rid of the unwanted self
console.log(bits2);

split string and leave the separators intact

I cannot find a good way to split a string using a separator string but leave the separator as the prefix of each element of the resulting array:
from
var s = 'blah0__blah1__blah2';
I need to get
['blah0', '__blah1', '__blah2']
the closest thing that I could get was
s.split(/(__)/);
which returns
['blah0', '__', 'blah1', '__', 'blah2']
but this I would need to traverse to merge the underscores.
Is there a better way?
EDIT:
here is my best effort so far:
'blah__blah1__blah2'.split(/(__[^_]+)/)
// => ["blah", "__blah1", "", "__blah2", ""]
still, there are empty strings in the output...
How about this:
var s = 'blah0__blah__blah'
var s_split = s.match(/(__)?(.(?!__))+./g)
console.log(s_split)
I'm pretty sure it's much more costly (time and memory wise) than simply reiterating and joining after a regular split.
If you replace __ with your separator it should work fine for most cases.
A two-step process.
var s = 'blah0__blah1__blah2';
var blahs = s.split('__');
var scoreBlahs = blahs.map(preScore);
alert(scoreBlahs);
function preScore(b) {
var x;
var result = x.concat('__',b);
return result;
}
'blah0__blah1__blah2'.match(/^[^_]+|_+[^_]+/g);
["blah0", "__blah1", "__blah2"]
Seems to give you what you want. Though It may vary, if your input isn't exactly as you show it.
Just prepend the seperator after you seperate the string
var value = "a,b,c";
var splitter = value.split(",");
for(var i = 0; i < splitter.length; i++) {
alert("," + splitter[i]);
}
Since you know the separator - just add it again later on:
var s = 'blah0__blah1__blah2';
var sep = '__';
var arr = s.split(sep);
for (var i = 1; i < arr.length; i++) {
arr[i] = sep + arr[i];
}
console.log(arr);
You could insert a secondary separator, and split on that, leaving the original intact.
var s = 'blah0__blah1__blah2';
s = s.replace('_', '_$');
s.split('$');

Whole word match in JavaScript in an Array

I've looked high and low for this, with no real idea how to do it now... my scenario:
var strArray = ['Email Address'];
function searchStringInArray(str, strArray) {
for (var j = 0; j < strArray.length; j++) {
if (strArray[j].match(str)) return j;
}
return -1;
}
var match = searchStringInArray('Email', strArray);
Email does NOT equal Email Address... however .match() seems to match the two up, when it shouldn't. I want it to match the exact string. Anyone have any idea how I do this?
You already have .indexOf() for the same thing you are trying to do.
So rather than looping over, why not use:
var match = strArray.indexOf('Email');
String.match is treating your parameter 'Email' as if it is a regular expression. Just use == instead:
if (strArray[j] == str) return j;
From the Mozilla Development Network page on String.match:
If a non-RegExp object obj is passed, it is implicitly converted to a
RegExp by using new RegExp(obj)
Alternatively using RegExp
Use ^ and $
var str = "Email";
new RegExp(str).test("Email address")
Result: true
And for this:
var str = "Email";
new RegExp("^" + str + "$").test("Email address")
Result: false

need a regular expression to search a matching last name

I have a javascript array which holds strings of last names.
I need to loop this array and separate out the last names which match a given string.
var names = ['woods','smith','smike'];
var test = 'smi';
var c = 0;
var result = new Array();
for(var i = 0; i < names.length; i++)
{
if(names[i].match(test))// need regular expression for this
result[c++] = names[i];
}
return result;
name should match the test string even if the test lies within the name. so... mik should match 'Mike' and 'Smike' also.
Any help is really appreciated!
You can create a regex from a string:
var nameRe = new RegExp("mik", "i");
if(names[i].match(nameRe))
{
result.push(names[i]);
}
Make sure to escape regex meta-characters though - if your string may contain them. For example ^, $ may result in a miss-match, and *, ? ) and more may result in an invalid regex.
More info: regular-expressions.info/javascript
You can do this without regex:
if (names[i].toLowerCase().indexOf(test.toLowerCase()) >= 0)
// ...
Javascript string .search is what you're looking for.. You don't even need regex although search supports that too.
var names = ['woods','smith','smike'];
var test = 'smi';
var c = 0;
var result = new Array();
for(var i = 0; i < names.length; i++)
{
if(names[i].toLowerCase().search(test))// need regular expression for this
result.push(names[i]);
}
return result;
You can do this with one regex.
var r = new RegExp(names.join('|'), "igm");
'woods smith'.match(r);
You don't need regex for this, so I'd recommend using string manipulation instead. It's almost (almost!) always better to use string functions instead of regex when you can: They're usually faster, and it's harder to make a mistake.
for(var i = 0; i < names.length; i++)
{
if(names[i].indexOf(test) > -1)
//match, do something with names[i]...
}

Categories