Counting items based on multiple separators? - javascript

I need to count the number of email addresses that a user inputs. Those addresses could be separated by any of the following:
Comma followed by no space - a#example.com,c#example.com.com
Comma followed by any number of spaces (ie. someone might have a comma follow by 3 spaces or just 1) - a#example.com, c#example.com.com
Only white space - a#example.com c#example.com.com
New line
What's a good way to clean that up and reliably count the addresses?
I assume regular 'ole javascript could handle this, but for what it's worth I am using jQuery.

The simplest way is just replace all commas with whitespaces, then, split your string based on blank spaces. No need for conditions.
Here's a fiddle with an example on that.

var emails = input.split(/[\s,]+/);
FIDDLE

var str="YOUR_STR",
arr = [];
if( str.indexOf(',') >= 0 ) {
// if comma found then replace all extra space and split with comma
arr = str.replace(/\s/g,'').split(',');
} else {
// if comma not found
arr = str.split(' ');
}

var l = "a#example.com,c#example.com.com a#example.com, c#example.com.com a#example.com c#example.com.com";
var r = l.split(/ |, |,/);
Regular expressions make that fairly easy.
If there is change of more than one space, the regex can be changed a bit.
var r = l.split(/ +|, +|,/);

Related

JavaScript: How to find and retrieve numbers from a string

I'm using RPG Maker MV which is a game creator that uses JavaScript to create plugins. I have a plugin in JavaScript already, however I'm trying to edit a part of the plugin so that it basically checks if a certain string exists in a character in the game and if it does, then sets specific variables to numbers within that string.
for (var i = 0; i < page.list.length; i++) {
if (page.list[i].code == 108 && page.list[i].parameters[0].contains("<post:" + (n) + "," + (n) + ">")) {
var post = page.list[i].parameters[0];
var array = post.split(',');
this._origMovement.x = Number(array[1]);
this._origMovement.y = Number(array[1]);
break;
};
};
So I know the first 2 lines work and contains works when I only put a specific string. However I can't figure out how to check for 2 numbers that are separated by a comma and wrapped in '<>' tags, without knowing what the numbers would be.
Then it needs to extract those numbers and assign one to this._origMovement.x and the other to this._origMovement.y.
Any help would be greatly appreciated.
This is one of those rare cases where I'd use a regular expression. If you haven't come across regular expressions before I suggest reading an introduction to them, such as this one: https://regexone.com/
In your case, you probable want something like this:
var myRegex = /<post:(\d+),(\d+)>/;
var matches = myParameter.match(myRegex);
this._origMovement.x = matches[1]; //the first number
this._origMovement.y = matches[2]; //the second number
The myRegex variable is a regular expression that looks for the pattern you describe, and has 2 capture groups which look for a string of one or more digits (\d+ means "one or more digits"). The result of the .match() call gives you an array containing the entire match and the results of the capture groups.
If you want to allow for decimal numbers, you'll need to use a different capture group that allows for a decimal point, such as ([\d\.]+), which means "a sequence of one or more digits and decimal points", or more sophisticated, (\d+\.?\d*), which is "a sequence of one or more digits, following by an optional decimal point, followed by zero or more digits).
There are lots of good tutorials around to help you write good regular expressions, and sites that will help you live-test your expressions to make sure they work correctly. They're a powerful tool, but be careful not to over-use them!
Got it to work. For anyone who may ever be interested, the code is below.
for (var i = 0; i < page.list.length; i++) {
if (page.list[i].code == 108 && page.list[i].parameters[0].contains("<post:")) {
var myRegex = /<post:(\d+),(\d+)>/;
var matches = page.list[i].parameters[0].match(myRegex);
this._origMovement.x = matches[1]; //the first number
this._origMovement.y = matches[2]; //the second number
break;
}
};

Javascript iterate over string looking for multiple character sets

Ok, so I know how to do a standard loop to iterate over a string to find a character or a word that matches a single character or word, but in this instance, I have multiple character sets that I am looking for. Some are letters, some have characters (including protected ones). I can't split it into an array of words on space or anything like that because the character sets might not have a space, so wouldn't split. I suspect I'm going to have to do a regex, but I'm not sure how to set it up. This is basically the pseudo code of what I'm trying to do and I'd appreciate any tips on how to move forward. I apologize if this is an easy thing and I'm missing it, I'm still working on my javascript.
Pseudo code:
var string = "This *^! is abdf random&!# text to x*?ysearch for character sets";
var tempSet = [];
// start a typical for loop
for(string.length bla bla...){
// look for one of those four character sets and if it hits one
if(foundSet == "abdf" | "x*?y" | "*^!" | "&!#")
// push that character set to the tempSet array
tempSet.push(foundSet);
// continue searching for the next set until the string is done
console.log(tempSet);
//expected result = ["*^!", "abdf", "&!#", "x*?y"]
and all the sets are in the array in the order in which they appeared in the string
there is obviously more, but that part I can handle. It's this line
if(??? == "abdf" | "x*?y" | "*^!" | "&!#")
that I don't know really how to tackle. I suspect it should be some kind of regex but can you have a regex like that with a | when doing an if statement? I've done them with a | when doing a map/replace but I've never used a regex in a loop. I also don't know how to get it to search multiple characters at a time. Some of the character sets are 3, some are 4 characters long.
I would appreciate any help or if you have a suggestion on how to approach this in an easier way, that would be great.
Thanks!
You can use a regular expression. Just list all your strings as alternatives separated by |. Characters that have special meaning in regular expressions (e.g. *, ?, ^, $) will need to be escaped with \ (you can safely escape any non-alphanumeric characters -- some will be redundant).
var string = "This *^! is abdf random&!# text to x*?ysearch for character sets";
var tempSet = string.match(/abdf|x\*\?y|\*\^!|&!#/g);
console.log(tempSet);
If you need a loop you can call RegExp.prototype.exec() in a loop.
var string = "This *^! is abdf random&!# text to x*?ysearch for character sets";
var regex = /abdf|x\*\?y|\*\^!|&!#/g;
var tempSet = [];
while (match = regex.exec(string)) {
tempSet.push(match[0]);
}
console.log(tempSet);
A bit more of a manual method than Barmar's excellent RegEx, but it was fun to put together and shows the pieces maybe a bit more clearly:
var text = "This *^! is abdf random&!# text to x*?ysearch for character sets",
detect = ["abdf", "x*?y", "*^!", "&!#"],
haystack = '',
found = [];
text.split('').forEach(function(letter){
haystack += letter;
detect.forEach(function(needle){
if (haystack.indexOf(needle) !== -1
&& found.indexOf(needle) === -1) {
found.push(needle);
}
});
});
console.log(found);
I think what you're looking for is the includes() function.
var sample = "This *^! is abdf random&!# text to x*?ysearch for character
sets";
var toSearch = ["*^!", "abdf", "&!#", "x*?y"];
var tempSet = [];
for (var i = 0; i < toSearch.length; i++) {
if (sample.includes(toSearch[i]){
tempSet.push(toSearch[i]);
}
}
console.log(tempSet);
//expected result = ["*^!", "abdf", "&!#", "x*?y"]
This way you can iterate through an entire array of whatever strings you're searching for and push all matching elements to tempSet.
Note: This is case sensitive, so make sure you consider your check accordingly.
I would just add this as a comment to Kevin's answer if I was able to, but if you need IE support you can also check searchString.indexOf(searchToken) !== -1.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf

Regular expression, specify a number of loops

This regular expression looks for words with 3 or less characters so that a non-breaking space can be placed in before them.
smallwords = /(\s|^)(([a-zA-Z-_(]{1,2}('|’)*[a-zA-Z-_,;]{0,1}?\s)+)/gi, // words with 3 or less characters
Is there a way, to make the expression only apply itself to 2 words in a row?
Example
Currently, the string:
Singapore, the USA and Vietnam.
will be turned into:
Singapore, the USA and Vietnam.
if the expression only applied to 2 words in a row it would show
Singapore, the USA and Vietnam.
here's the full script:
ragadjust = function (s, method) {
if (document.querySelectorAll) {
var eles = document.querySelectorAll(s),
elescount = eles.length,
smallwords = /(\s|^)(([a-zA-Z-_(]{1,2}('|’)*[a-zA-Z-_,;]{0,1}?\s)+)/gi, // words with 3 or less characters
while (elescount-- > 0) {
var ele = eles[elescount],
elehtml = ele.innerHTML;
if (method == 'small-words' || method == 'all')
// replace small words
elehtml = elehtml.replace(smallwords, function(contents, p1, p2) {
return p1 + p2.replace(/\s/g, ' ');
});
ele.innerHTML = elehtml;
}
}
};
This is from RagAdjust
I know that this is not what you are asking for, but I figured a code review wouldn't hurt:
I think the word boundary \b is better, in this case, than \s|^.
You have the A-Z and a-z characters in your match, yet you are use the i case insensitive operator.
{0,1}? is redundant - either use the ? to make it optional, or use {0,1} to make it match zero or one times.
If your are going to have a dash in your character set put it at the end so that you don't have an ambiguous regex, for example this [a-z_-] is much better than [a-z-_].
If you don't need to capture a value, use the non-capturing parenthesis (?:).
So, here's your cleaned up regex:
/\b((?:[a-z_(-]{1,2}(?:'|’)*[a-z_,;-]?\s)+)/gi
I'm pretty sure the '|’ bit is some sort of typo when you pasted this in from your editor. Not sure what it is supposed to be.
This doesn't quite solve the issue the way you suggested but it does reduce the number of non breaking spaces that end up in the string. But it might give you some insight. Because you have the trailing g on both regex replacements, you're doing global replace. If you instead loop it with some max number of fixes, things work out a little differently.
Try changing the max number of replacements. I think the other thing that happens here (in my modified code) is that after you make one replacement, the spaces and small words are gone because you jammed in a nbsp which may or may not solve the issue you're trying to get around.
Here's my replacement function (simplified from your original). The basic mod is to remove the g from the regex's and add the loop. You should check out the codepen to see the full deal
var new_ragadjust = function (contents) {
MAX_NUMBER_OF_REPLACEMENTS = 5;
smallwords = /(\s|^)(([a-zA-Z-_(]{1,2}('|’)*[a-zA-Z-_,;]{0,1}?\s)+)/i; // words with 3 or less characters
var ii = 0;
var c = contents;
for (;ii < MAX_NUMBER_OF_REPLACEMENTS; ++ii) {
c = c.replace(smallwords, function(contents, p1, p2) {
return p1 + p2.replace(/\s/, ' ');
});
}
return c;
};
Codepen
http://cdpn.io/DKLtc
Also, to see the difference, you need to inspect elements to actually see where the nbsps end up (as you probably already knew).

Regex getting two specific characters within square brackets

Not too well-versed with Regex. I have a string like this:
var str = "WOMEN~~Accessories >Underwear~~Socks, Tights & Leggings"
Using Javascript, I want to split at: ~~, &, > and , including potential white space surrounding them.
So far I've got:
var arr = str.split(/[\s>&,]/g);
for (var i = 0; i<arr.length; i++){
if(arr[i]){accepted.push(arr[i])}
}
This doesn't account for multiple characters though (and I'm sure there's a better way to regex in the white space rather than a for loop after the fact!) and the ~~ isn't selected.
I'm thinking something along the lines of /[\s>&,[~~]]/g but this doesn't work. How can I do this with regex?
Try this:
/\s*[\s>&,\[\]~]+\s*/g
Description
Demo
http://jsfiddle.net/p7FFD/
var arr = str.split(/(~~|[\s>&,]+)/g);
So you're splitting on either ~~ or any combination of whitespace, ampersands, greater than (>) and commas.

Javascript Regex - 9 chars long, starting with 'SO-' and ending with 6 numbers

Regular expressions are simply evil in my mind and no matter how many times I read any documentation I just cannot seem to grasp even the simplest of expressions!
I am trying to write what must be a very simple expression to query a variable in javascript but I just cannot get it to work properly.
I am trying to validate the following:-
The string must be 9 characters long, starting with SO- (case insensitive eg So-, so-, sO- and SO-) followed by 6 numbers.
So the following should all match
SO-123456,
So-123456,
sO-456789,
so-789123
but the following should fail
SO-12d456,
SO-1234567
etc etc
I have only managed to get this far so far
var _reg = /(SO-)\d{6}/i;
var _tests = new Array();
_tests[0] = "So-123456";
_tests[1] = "SO-123456";
_tests[2] = "sO-456789";
_tests[3] = "so-789123";
_tests[4] = "QR-123456";
_tests[5] = "SO-1234567";
_tests[6] = "SO-45k789";
for(var i = 0; i < _tests.length; i++){
var _matches = _tests[i].match(_reg);
if(_matches && _matches.length > 0)
$('#matches').append(i+'. '+_matches[0] + '<br/>');
}
Please see http://jsfiddle.net/TzHKd/ for above example
Test number 5 is matching although it should fail as there are 7 numbers and not 6.
Any assistance would be greatly appreciated.
Cheers
use this regexp instead
/^(so-)\d{6}$/i;
without ^ (string starting with) or $ (string ending with) you're looking for a generic substring match (that's the reason why when you have 7 digits your regexp return true).
By using the anchors ^ and $ (matching beginining of line and end of line respectively), you can make the regex match the whole line. Otherwise, the match with return true as soon as the characters in the regex are matched.
So, you will apply it like this:
var _reg = /^(so-)\d{6}$/i;

Categories