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]...
}
Related
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
)
I have the below code which works. But would using RegExp be a more efficient code?
(Return true if the string in the first element of the array contains the letters of the string in the second element of the array.)
function mutation(arr) {
var first = arr[0].split("");
var second = arr[1].split("");
var answer = false;
for (var e = 0; e < second.length; e++) {
answer = false;
for (var i = 0; i < first.length; i++) {
if (first[i] === second[e]) {
answer = true;
}
}
}
return answer;
}
mutation(['hello', 'hey']);
Using regex to do this check as the code you've shown above:
var a = 'hello how are you';
var b ='hey you there';
var result = new RegExp(b.split(/ +/)[0].split('').join('|')).test( a.split(/ +/)[0] );
//=> true
First split(/ +/)[0] is used to get first word from both strings
Then split('') is used to get each letter from first word of 2nd input
join('|') is used to join them by | to get regex as h|e|y
new RegExp is used for construct a regex object
test is used to execute the regex
In ES6 it can be written as follows:
function mutation(lettersSource, checkedString) {
var referenceLetters = new Set(lettersSource); // get letters from string
var usedLetters = new Set(checkedString);
// create union of letters in both strings
var lettersUnion = new Set([...usedLetters, ...referenceLetters]);
return lettersUnion.size === referenceLetters.size;
}
This solution is O(m+n+k) where m and n is number of letters in strings, and k is number of used letters.
Your solution is O(m*n), quite inefficient.
In ES5 Object can be used as well as dictionary to collect only letters, but it will be slower for many possible letters (Unicode strings).
If you don't have to care about memory usage, you can create dense array using .charCodeAt to index elements in array for O(1) access to checking if elements exists (O(m+n+k)).
Is there a better way than what I have (through regex, for instance) to turn
"div#container.blue"
into this
["div", "#container", ".blue"];
Here's what I've have...
var arr = [];
function process(h1, h2) {
var first = h1.split("#");
arr.push(first[0]);
var secondarr = first[1].split(".");
secondarr[0] = "#" + secondarr[0];
arr.push(secondarr[0]);
for (i = 1; i< secondarr.length; i++) {
arr.push(secondarr[i] = "." + secondarr[i]);
}
return arr;
}
Why not something like this?
'div#container.blue'.split(/(?=[#.])/);
Because it's simply looking for a place where the next character is either # or the literal ., this does not capture anything, which makes it a zero length match. Because it's zero-length match, nothing is removed.
As you've probably found, the issue is that split removes the item you're splitting on. You can solve that with regex capturing groups (the parenthesis):
var result = 'div#container.blue'.split(/(#[^#|^.]*)|(\.[^#|^.]*)/);
Now we've got the issue that result contains a lot of falsy values you don't want. A quick filter fixes that:
var result = 'div#container.blue'.split(/(#[^#|^.]*)|(\.[^#|^.]*)/).filter(function(x) {
return !!x;
});
Appendix A: What the heck is that regex
I'm assuming you're only concerned with # and . as characters. That still gives us this monster: /(#[^#|^.]*)|(\.[^#|^.]*)/
This means we'll capture either a # or ., and then all the characters up until the next # or . (remembering that a period is significant in regex, so we need to escape it, unless we're inside the brackets).
I've written an extensions of the Script type for you. It allows you to choose which delimiters to use, passing them in a string:
String.prototype.splitEx = function(delimiters) {
var parts = [];
var current = '';
for (var i = 0; i < this.length; i++) {
if (delimiters.indexOf(this[i]) < 0) current += this[i];
else {
parts.push(current);
current = this[i];
}
}
parts.push(current);
return parts;
};
var text = 'div#container.blue';
console.log(text.splitEx('#.'));
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('$');
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