retrieving regular expression match group values - javascript

Here is the script;:
var output = []
output = this.getField("SelectedSoftware").value.match(/\$(\d{1,4}\.\d\d)/g);
Example text from the field:
Automate, Audition ($500.00), Citrix Receiver, AutoCAD ($54.93), Clarity Studio ($748.23), Audacity ($300.00), Audition ($500.00), Business Objects Dashboard, Audition ($500.00),
The problem I have is getting just the cost numbers so they can be added together to display a total. (?<=\$) doesn't seem to work. so I grouped the rest of the expression in Parentheses. However, I'm not sure how to get those group values instead of the full matches.

RegExp.exec(string) should be really helpful. In fact, it's the only way to obtain capture groups from a string. The implementation is a bit tough though, since .exec() only returns a single result.
Sample code:
var regex = /\$(\d{1,4}\.\d\d)/g,
text = this.getField("SelectedSoftware").value,
prices = [],
total = 0,
num;
// Assignments always return the value that is assigned.
// .exec will return null if no matches are found.
while((val = regex.exec(text)) !== null){
// Capture groups are referenced with 'val[x]', where x is the capture group number.
num = parseFloat(val[1]);
total += num;
prices.push(num);
}
Here's a fiddle.
This works because RegExp objects have a property called .lastIndex which it bases the next .exec() search on.
You can read more about .exec() on the MDN.

You can use (?: ) to create non-capturing groups, but I don't think you need it in this case.
MDN: Working with regular expressions
exec: A RegExp method that executes a search for a match in a string.
It returns an array of information. test: A RegExp method that tests
for a match in a string. It returns true or false. match: A String
method that executes a search for a match in a string. It returns an
array of information or null on a mismatch. search: A String method
that tests for a match in a string. It returns the index of the match,
or -1 if the search fails. replace: A String method that executes a
search for a match in a string, and replaces the matched substring
with a replacement substring. split: A String method that uses a
regular expression or a fixed string to break a string into an array
of substrings.
What you need is RegExp.exec, which will return an array of information form which you can get the captured group.
It returns an array with the whole match in [0], then each captured group in the following array slots. So what you want is:
var price = /\$(\d{1,4}\.\d\d)/.exec("$59.99")[1];

I have is getting just the cost numbers so they can be added together to display a total. String.prototype.match
always returns an array as you want.
See this complete DEMO
var output = []
output = "Automate, Audition ($500.00), "
+"Citrix Receiver, AutoCAD ($54.93), "+
+"Clarity Studio ($748.23), Audacity "
+"($300.00), Audition ($500.00), Business "
+"Objects Dashboard, Audition ($500.00),"
.match(/\$(\d{1,4}\.\d\d)/g);
Output:
["$500.00", "$54.93", "$748.23", "$300.00", "$500.00", "$500.00"]
Now you can simply add all number using This regex /(\d{1,4}\.\d\d)/g.
Getting sum of these values:
var total = 0;
for(var _=0; _<output.length; _++)
total += parseFloat(output[_]);
See OUTPUT 2603.16

Related

Obtain arguments from a string seperated by a space and convert an argument in an array format to an array

I have arguments that will be passed by the user for a command. Each argument for a command will be seperated with a space, which will represent a new argument. Example: "arg1 arg2 arg3" converts to ["arg1", "arg2", "arg3"] where the output is a JS array. This can be done with a simple .split(" ").
However, my problem begin when trying to format an array as a command argument. My goal is to allow the user to enter an agument in the format of an array (e.g. Starts with [ may contain multiple elements seperated by a , and ends with a ]) so for example: "arg1 [elem1, elem2] arg3" converts to ["arg1", ["elem1", "elem2"], "arg3"] where the inner and outer array is a JS array.
I have tried using JSON.Parse() however, each element would require the user to have " at the start of each element which is too complex for the user and non essential to be inputting. Also, the elements may not always intend to be a string and may be Boolean, Number or a custom type.
As of currently, this has been my best solution but misses some requirements and also is non functional when an array has a space inside.
s.split(/[\[\]]|\s+/).filter(arg => arg.length > 1);
I have come up with some other solutions but all are missing one thing or another in the required specification set above. A solution that can handle nested arrays would be nice however it is non-essential and could make the solution alot more complex than it needs to be.
Let's assume no funny characters as the input. Also nesting not allowed.
var str = "arg1 [ elem1 , elem2,elem3 ] arg3";
console.log(str)
// removing white spaces from the [ array ]
str = str.replace(/\s*,\s*/g, ',');
str = str.replace(/\[\s*/g, '[');
str = str.replace(/\s*\]/g, ']');
// now split on words
var arr = str.split(/\s+/);
arr = arr.map(function(elem) {
// if begins with [ it is assumed to be an array to be splitted
return elem.charAt(0) == '[' ? elem.slice(1, -1).split(",") : elem;
})
console.log(arr)

javascript getting a faulty result using a regular expression

In my web page, I have:
var res = number.match(/[0-9\+\-\(\)\s]+/g);
alert(res);
As you can see, I want to get only numbers, the characters +, -, (, ) and the space(\s)
When I tried number = '98+66-97fffg9', the expected result is: 98+66-979
but I get 98+66-97,9
the comma is an odd character here! How can eliminate it?
Its probably because you get two groups that satisfied your expression.
In other words: match mechanism stops aggregating group when it finds first unwanted character -f. Then it skips matching until next proper group that, in this case, contains only one number - 9. This two groups are separated by comma.
Try this:
var number = '98+66-97fffg9';
var res = number.match(/[0-9\+\-\(\)\s]+/g);
// res is an array! You have to join elements!
var joined = res.join('');
alert(joined);
You're getting this because your regex matched two results in the number string, not one. Try printing res, you'll see that you've matched both 98+66-979 as well as 9
String.match returns an array of matched items. In your case you have received two items ['98+66-97','9'], but alert function outputs them as one string '98+66-97,9'. Instead of match function use String.replace function to remove(filter) all unallowable characters from input number:
var number = '98+66-97fffg9',
res = number.replace(/[^0-9\+\-\(\)\s]+/g, "");
console.log(res); // 98+66-979
stringvariable.match(/[0-9\+\-\(\)\s]+/g); will give you output of matching strings from stringvariable excluding unmatching characters.
In your case your string is 98+66-97fffg9 so as per the regular expression it will eliminate "fffg" and will give you array of ["98+66-97","9"].
Its default behavior of match function.
You can simply do res.join('') to get the required output.
Hope it helps you
As per documents from docs, the return value is
An Array containing the entire match result and any parentheses-captured matched results, or null if there were no matches.
S,your return value contains
["98+66-97", "9"]
So if you want to skip parentheses-captured matched results
just remove g flag from regular expression.
So,your expression should like this one
number.match(/[0-9\+\-\(\)\s]+/); which gives result ["98+66-97"]

Whats wrong with this regex logic

I am trying to fetch the value after equal sign, its works but i am getting duplicated values , any idea whats wrong here?
// Regex for finding a word after "=" sign
var myregexpNew = /=(\S*)/g;
// Regex for finding a word before "=" sign
var mytype = /(\S*)=/g;
//Setting data from Grid Column
var strNew = "QCById=20";
var matchNew = myregexpNew.exec(strNew);
var newtype = mytype.exec(strNew);
alert(matchNew);
https://jsfiddle.net/6vjjv0hv/
exec returns an array, the first element is the global match, the following ones are the submatches, that's why you get ["=20", "20"] (using console.log here instead of alert would make it clearer what you get).
When looking for submatches and using exec, you're usually interested in the elements starting at index 1.
Regarding the whole parsing, it's obvious there are better solution, like using only one regex with two submatches, but it depends on the real goal.
You can try without using Regex like this:
var val = 'QCById=20';
var myString = val.substr(val.indexOf("=") + 1);
alert(myString);
Presently exec is returning you the matched value.
REGEXP.exec(SOMETHING) returns an array (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec).
The first item in the array is the full match and the rest matches the parenthesized substrings.
You do not get duplicated values, you just get an array of a matched value and the captured text #1.
See RegExp#exec() help:
If the match succeeds, the exec() method returns an array and updates properties of the regular expression object. The returned array has the matched text as the first item, and then one item for each capturing parenthesis that matched containing the text that was captured.
Just use the [1] index to get the captured text only.
var myregexpNew = /=(\S*)/g;
var strNew = "QCById=20";
var matchNew = myregexpNew.exec(strNew);
if (matchNew) {
console.log(matchNew[1]);
}
To get values on both sides of =, you can use /(\S*)=(\S*)/g regex:
var myregexpNew = /(\S*)=(\S*)/g;
var strNew = "QCById=20";
var matchNew = myregexpNew.exec(strNew);
if (matchNew) {
console.log(matchNew[1]);
console.log(matchNew[2]);
}
Also, you may want to add a check to see if the captured values are not undefined/empty since \S* may capture an empty string. OR use /(\S+)=(\S+)/g regex that requires at least one non-whitespace character to appear before and after the = sign.

Regular Expression with multiple words (in any order) without repeat

I'm trying to execute a search of sorts (using JavaScript) on a list of strings. Each string in the list has multiple words.
A search query may also include multiple words, but the ordering of the words should not matter.
For example, on the string "This is a random string", the query "trin and is" should match. However, these terms cannot overlap. For example, "random random" as a query on the same string should not match.
I'm going to be sorting the results based on relevance, but I should have no problem doing that myself, I just can't figure out how to build up the regular expression(s). Any ideas?
The query trin and is becomes the following regular expression:
/trin.*(?:and.*is|is.*and)|and.*(?:trin.*is|is.*trin)|is.*(?:trin.*and|and.*trin)/
In other words, don't use regular expressions for this.
It probably isn't a good idea to do this with just a regular expression. A (pure, computer science) regular expression "can't count". The only "memory" it has at any point is the state of the DFA. To match multiple words in any order without repeat you'd need on the order of 2^n states. So probably a really horrible regex.
(Aside: I mention "pure, computer science" regular expressions because most implementations are actually an extension, and let you do things that are non-regular. I'm not aware of any extensions, certainly none in JavaScript, that make doing what you want to do any less painless with a single pattern.)
A better approach would be to keep a dictionary (Object, in JavaScript) that maps from words to counts. Initialize it to your set of words with the appropriate counts for each. You can use a regular expression to match words, and then for each word you find, decrement the corresponding entry in the dictionary. If the dictionary contains any non-0 values at the end, or if somewhere a long the way you try to over-decrement a value (or decrement one that doesn't exist), then you have a failed match.
I'm totally not sure if I get you right there, so I'll just post my suggestion for it.
var query = "trin and is",
target = "This is a random string",
search = { },
matches = 0;
query.split( /\s+/ ).forEach(function( word ) {
search[ word ] = true;
});
Object.keys( search ).forEach(function( word ) {
matches += +new RegExp( word ).test( target );
});
// do something useful with "matches" for the query, should be "3"
alert( matches );
So, the variable matches will contain the number of unique matches for the query. The first split-loop just makes sure that no "doubles" are counted since we would overwrite our search object. The second loop checks for the individuals words within the target string and uses the nifty + to cast the result (either true or false) into a number, hence, +1 on a match or +0.
I was looking for a solution to this issue and none of the solutions presented here was good enough, so this is what I came up with:
function filterMatch(itemStr, keyword){
var words = keyword.split(' '), i = 0, w, reg;
for(; w = words[i++] ;){
reg = new RegExp(w, 'ig');
if (reg.test(itemStr) === false) return false; // word not found
itemStr = itemStr.replace(reg, ''); // remove matched word from original string
}
return true;
}
// test
filterMatch('This is a random string', 'trin and is'); // true
filterMatch('This is a random string', 'trin not is'); // false

Get part of string into variable

i need to get part of string into variable. (note, i will always use exactly 4 names)
var names = "Andrew Peter Bob Mark"
I need to get the last one to
var last = "Mark"
Thanks for help in advance
var last = names.split(/\s+/).pop(); // "Mark"
Explanation: .split splits a string on a given separator and returns an array. /\s+/ is a regular expression for "one or more whitespaces" (space, tab, newline, etc). .pop() grabs the last value from the array that .split returns.
Answer from Roatin Marth is correct, but in case if you need 4 times faster version (in IE) of same operation:
var last = names.substr(names.lastIndexOf(" "));
It is working without regular expressions and temp arrays - just with index operations of string.

Categories