How to get parameter value inside a string? - javascript

Here's a thing i've been trying to resolve...
We've got some data from an ajax call and the result data is between other stuff a huge string with key:value data. For example:
"2R=OK|2M=2 row(s) found|V1=1,2|"
Is it posible for js to do something like:
var value = someFunction(str, param);
so if i search for "V1" parameter it will return "1,2"
I got this running on Sql server no sweat, but i'm struggling with js to parse the string.
So far i'm able to do this by a VERY rudimentary for loop like this:
var str = "2R=OK|2M=2 row(s) found|V1=1,2|";
var param = "V1";
var arr = str.split("|");
var i = 0;
var value = "";
for(i = 0; i<arr.length; ++i){
if( arr[i].indexOf(param)>-1 ){
value = arr[i].split("=")[1];
}
}
console.log(value);
if i put that into a function it works, but i wonder if there's a more efficient way to do it, maybe some regex? but i suck at it. Hopefully somebody may shine a light on this for me?
Thanks!

This seems to work for your specific use-case:
function getValueByKey(haystack, needle) {
if (!haystack || !needle) {
return false;
}
else {
var re = new RegExp(needle + '=(.+)');
return haystack.match(re)[1];
}
}
var str = "2R=OK|2M=2 row(s) found|V1=1,2|",
test = getValueByKey(str, 'V1');
console.log(test);
JS Fiddle demo.
And, to include the separator in your search (in order to prevent somethingElseV1 matching for V1):
function getValueByKey(haystack, needle, separator) {
if (!haystack || !needle) {
return false;
}
else {
var re = new RegExp('\\' + separator + needle + '=(.+)\\' + separator);
return haystack.match(re)[1];
}
}
var str = "2R=OK|2M=2 row(s) found|V1=1,2|",
test = getValueByKey(str, 'V1', '|');
console.log(test);
JS Fiddle demo.
Note that this approach does require the use of the new RegExp() constructor (rather than creating a regex-literal using /.../) in order to pass variables into the regular expression.
Similarly, because we're using a string to create the regular expression within the constructor, we need to double-escape characters that require escaping (escaping first within the string and then escaping within in the created RegExp).
References:
RegExp.
String.match().

This should work for you and it's delimiters are configurable (if you wish to parse a similar string with different delimiters, you can just pass in the delimiters as arguments):
var parseKeyValue = (function(){
return function(str, search, keyDelim, valueDelim){
keyDelim = quote(keyDelim || '|');
valueDelim = quote(valueDelim || '=');
var regexp = new RegExp('(?:^|' + keyDelim + ')' + quote(search) + valueDelim + '(.*?)(?:' + keyDelim + '|$)');
var result = regexp.exec(str);
if(result && result.length > 1)
return result[1];
};
function quote(str){
return (str+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
}
})();
Quote function borrowed form this answer
Usage examples:
var str = "2R=OK|2M=2 row(s) found|V1=1,2|";
var param = "V1";
parseKeyValue(str, param); // "1,2"
var str = "2R=OK&2M=2 row(s) found&V1=1,2";
var param = "2R";
parseKeyValue(str, param, '&'); // "OK"
var str =
"2R=>OK\n\
2M->2 row(s) found\n\
V1->1,2";
var param = "2M";
parseKeyValue(str, param, '\n', '->'); // "2 row(s) found"

Here is another approach:
HTML:
<div id="2R"></div>
<div id="2M"></div>
<div id="V1"></div>
Javascript:
function createDictionary(input) {
var splittedInput = input.split(/[=|]/),
kvpCount = Math.floor(splittedInput.length / 2),
i, key, value,
dictionary = {};
for (i = 0; i < kvpCount; i += 1) {
key = splittedInput[i * 2];
value = splittedInput[i * 2 + 1];
dictionary[key] = value;
}
return dictionary;
}
var input = "2R=OK|2M=2 row(s) found|V1=1,2|",
dictionary = createDictionary(input),
div2R = document.getElementById("2R"),
div2M = document.getElementById("2M"),
divV1 = document.getElementById("V1");
div2R.innerHTML = dictionary["2R"];
div2M.innerHTML = dictionary["2M"];
divV1.innerHTML = dictionary["V1"];
Result:
OK
2 row(s) found
1,2

Related

How to creat a dynamic RegEx

I'm trying to match some words in a string. But I don't have a predefined number of words I need to find.
For example I search for Ubuntu 18 10 in ubuntu-18.10-desktop-amd64.iso.torrent would return true.
Or I could search for centos 7 in CentOS-7-x86_64-LiveGNOME-1804.torrent would also return true.
I don't need to check if it's lowercase or not.
What I tried :
$.get('interdit', function(data) {
var lines = data.split("\n");
$.each(lines, function(n, data_interdit) {
var url_check = $('textarea#url').val()
var split_forbidden = data_interdit.split(/[\s|,|_|.|-|:]+/);
var exist = 0;
$.each(split_forbidden, function(n, data) {
var n = url_check.search("^("+ data +")");
if(n != -1){
exist = 1
}else{
exist = 0
}
console.log('Forbidden: '+ data + ' Result: ' + n);
})
if(exist == 1){
console.log('found')
}
});
});
Sample data of the file interdit :
CentOS.7
Ubuntu-18
You want to look for existing words within the input string without the order being taken into account. You need to use positive lookaheads for this:
var search = 'Ubuntu 18 10';
var str = 'ubuntu-18.10-desktop-amd64.iso.torrent';
var re = new RegExp('^(?=.*' + search.split(/[\s,_.:-]+/).join(')(?=.*') + ')', 'i')
console.log(re.test(str));
This produces a regex as the following (with i flag set):
^(?=.*Ubuntu)(?=.*18)(?=.*10)
RegEx Array
Update
"The code give me an error jsbin.com/pecoleweyi/2/edit?js,console"
Although the question did not include unlikely input such as: *centos 7*, add the following line to escape the special characters that occur in input:
var esc = word.replace(/[.*+?^${}()|[\]\\]/gi, '\\$&');
and change the next line:
var sub = esc.replace(/\s/gi, '.');
The demo below will:
accept a string (str) to search and an array of strings (tgt) to find within the string,
.map() the array (tgt) which will run a function on each string (word)
escape any special characters:
var esc = word.replace(/[.*+?^${}()|[\]\\]/gi, '\\$&');
replace any spaces (/\s/g) with a dot (.):
var sub = esc.replace(/\s/g, '.');
then makes a RegExp() Object so a variable can be inserted in the pattern via template literal interpolation (say that ten times fast):
var rgx = new RegExp(`${sub}`, `gim`);
uses .test() to get a boolean: found = true / not found = false
var bool = rgx.test(str);
create an Object to assign the search string: word as a property and the boolean: bool as it's value.
var obj = {
[word]: bool
};
returns an array of objects:
[{"centos 7":true},{"Ubuntu 18 10":true}]
Demo
var str = `ubuntu-18.10-desktop-amd64.iso.torrent
CentOS-7-x86_64-LiveGNOME-1804.torrent`;
var tgt = [`centos 7`, `Ubuntu 18 10`, `corn flakes`, `gnome`, `Red Hat`, `*centos 7*`];
function rgxArray(str, tgt) {
var res = tgt.map(function(word) {
var esc = word.replace(/[.*+?^${}()|[\]\\]/gi, '\\$&');
var sub = esc.replace(/\s/gi, '.');
var rgx = new RegExp(`${sub}`, `gi`);
var bool = rgx.test(str);
var obj = {
[word]: bool
};
return obj;
});
return res;
}
console.log(JSON.stringify(rgxArray(str, tgt)));

I have to make a split function in JavaScript

Edit
sorry if the question wasn't clear
here is the question..
create your version of javascript split function,
you may use indexOf and substring to help.
so if i give you a string "heellloolllloolllo" and i want to remove "llll" the function should return "heellloooolllo"
This what I did so far:
function split() {
var entered_string = document.forms["form1"]["str"].value;
var deleted_char = document.forms["form1"]["char"].value;
var index = entered_string.indexOf(deleted_char);
var i = deleted_char.length;
var result;
var x ;
for (x = 0; x< entered_string.length; x++ )
{
if (index < 0) {
result = entered_string;
} else {
result = entered_string.substring(0, index) +entered_string.substring(index+i);
}
}
alert(result)
}
Use the replace() function with the g at the end of your regular expression. It's called a "global modifier".
var string = 'heellloolllloolllo';
var res = string.replace(/llll/g, '');
console.log(res)
If your substring is a variable then you need to construct a new Regex object and set the g as the second parameter.
var string = 'heellloolllloolllo';
var find = 'llll';
var regex = new RegExp(find,'g');
var res = string.replace(regex, '');
console.log(res)
There are other useful modifiers you can use:
g - Global replace. Replace all instances of the matched string in the provided text.
i - Case insensitive replace. Replace all instances of the matched string, ignoring differences in case.
m - Multi-line replace. The regular expression should be tested for matches over multiple lines.
See this post for more information, credit to #codejoe.
Using String#replace and RegExp (the clean way)
var str = 'llllheellloolllloolllollll';
var matchStr = 'llll';
function removeSubString(str, matchStr) {
var re = new RegExp(matchStr, 'g');
return str.replace(re,"");
}
console.log(removeSubString(str, matchStr));
Using String#indexOf and String#substring
var str = 'llllheellloolllloolllollll';
var matchStr = 'llll';
function removeSubString(str, matchStr) {
var index = str.indexOf(matchStr);
while(index != -1) {
var firstSubStr = str.substring(0, index);
var lastSubStr = str.substring(index + matchStr.length);
str = firstSubStr + lastSubStr;
index = str.indexOf(matchStr);
}
return str;
}
console.log(removeSubString(str,matchStr))

How to insert default value in the comma separated strings?

I have group of comma separated strings and if any string is not a numeric value, I need to insert "(1)".
"stack(2),flow,over(4),temp(7)" Here insert default value to flow(1)
"stack(2),flow(3),over(4),temp" Here insert default value to temp(1)
"stack,flow(3),over,temp" Here insert default value to stack(1),over(1),temp(1)
I have validation code to validate and insert default values where needed. Please help me how to insert a default value within parentheses.
javascript function :
var case1 = "stack(2),flow(2),over(4),temp(7)"; // - true
var case2 = "stack(2),flow(3),over(4),temp(k)"; // - false
var case3 = "stack(2),flow(2),over(4),temp(0"; // - false
var case4 = "stack(2),flow(2),over(,temp)"; // - false
var case5 = "stack(2),flow(2),over(4)temp(8)"; // - false
var case6 = "stack(1),flow(7),over,temp"; // - true
var case7 = "stack(1),flow(7),OVER,Temp"; // - true
var case8 = "stack(1),flow(7),over_r,temp_t"; // - true
function testCases(str)
{
var pattern = /^[a-z]+(?:\(\d+\))?(?:,[a-z]+(?:\(\d+\))?)*$/
return pattern.test(str);
}
The above function works for validation in jsfiddle
tl;dr
Use String.prototype.split and String.prototype.join to process each part of your string.
Details
If you want to apply custom fixes to your string, you need to split it in several parts and then process them. Once the job is done, concat all the parts together.
Implementation
Using Array.prototype.map (Warning: not compatible with IE 8 and below):
Demo on JSFiddle.
function testCases(str) {
return str.split(',').map(function(s) {
if (s.match(/^[a-z]+\(\d+\)$/i)) {
// string is valid
return s;
} else {
// you can do processing here based on the failure reason
return s + '(1)';
}
}).join(',');
}
Using a for loop (IE8-compatible):
function testCases(str) {
var parts = str.split(',');
var i = parts.length;
while (i--) {
var s = parts[i];
if (!s.match(/^[a-z]+\(\d+\)$/i)) {
// string is invalid
// you can do processing here based on the failure reason.
parts[i] = s + '(1)';
}
}
return parts.join(',');
}
Unfortunately, JavaScript doesn't have lookbehinds - they'd be very useful here. Instead, we have to cheat:
str = str.replace(/([^)])(,|$)/g,"$1(1)$2");
What this does is capture whatever character comes before the comma or end of string, provided it is not a close-parenthesis. It then inserts the (1) default value in that position.
var add_default = function(str, def) {
str = str.split(',');
for(var i = 0; i < str.length; ++i) {
if(!/\(\d+\)$/.test(str[i]))
str[i] += "(" + def + ")";
}
return str.join(',');
};
http://jsfiddle.net/BhVx3/3/
Here is a possible solution :
function fix(input) {
var r = /^(.*?)(?:\((\d*)\)?|\)?)$/,
input = input.split(','),
output = [],
item;
while (item = input.shift()) {
item = item.match(r);
item = item[1] + '(' + (item[2] || 1) + ')';
output.push(item);
}
return output.join();
}
var s = 'stack(2),over(4),flow,hello(0,kitty2)';
s = fix(s); // "stack(2),over(4),flow(1),hello(0),kitty2(1)"

Create JSON object from a path and template

I'm a lazy coder by nature, so would like to know that there's a lib out there that does the following before I write on:
var parser = PathParser('/{first}/{last}');
var actual = parser.parse('/fred/flintstone');
assertEquals({"first":"fred","last":"flintstone"}, actual);
The first string specifies a pattern, and the second extracts the relevant values and stores them in an object with keys corresponding to those in the pattern.
I've found the standard that does the expansion, but not the generation of the JSON Object.
You want to extract an array of keys from your first string and extract an array of values from the latter, where the value is preceded by a certain pattern and followed by a certain pattern.
There isn't an existing library that does this, but I have written an implementation. You can find a live demonstration here.
//## Extension to escape all regex special characters in a string ##
RegExp.quote = function(str) {
return (str + '').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
};
//## Parsing ##
var parser = PathParser('/{first}/{last}');
var actual = parser('/fred/flintstone');
//## Output ##
var pre = document.createElement('pre');
pre.innerHTML = JSON.stringify(actual, null, " ");
document.body.appendChild(pre);
//## The parser constructor ##
function PathParser(pattern) {
var keys = [];
var keyreg = /\{([a-zA-Z0-9]+)\}/g;
var result;
while ((result = keyreg.exec(pattern)) !== null) {
var pre = "^" + RegExp.quote(pattern.substring(0, result.index)).replace(/\\\{[a-zA-Z0-9]+\\\}/g, ".*");
var post = RegExp.quote(pattern.substring(keyreg.lastIndex)).replace(/\\\{[a-zA-Z0-9]+\\\}/g, ".*") + "$";
keys.push({
pre: pre,
post: post,
text: result[1]
});
}
function parser(valstring) {
var keyarr = keys;
var obj = {};
for (var i = 0; i < keyarr.length; i++) {
var valreg = new RegExp(keyarr[i].pre + "(.*)" + keyarr[i].post);
obj[keyarr[i].text] = valstring.match(valreg)[1];
}
return obj;
}
return parser;
}

Append number to a comma separated list

the list looks like:
3434,346,1,6,46
How can I append a number to it with javascript, but only if it doesn't already exist in it?
Assuming your initial value is a string (you didn't say).
var listOfNumbers = '3434,346,1,6,46', add = 34332;
var numbers = listOfNumbers.split(',');
if(numbers.indexOf(add)!=-1) {
numbers.push(add);
}
listOfNumbers = numbers.join(',');
Basically i convert the string into an array, check the existence of the value using indexOf(), adding only if it doesn't exist.
I then convert the value back to a string using join.
If that is a string, you can use the .split() and .join() functions, as well as .push():
var data = '3434,346,1,6,46';
var arr = data.split(',');
var add = newInt;
arr.push(newInt);
data = arr.join(',');
If that is already an array, you can just use .push():
var data = [3434,346,1,6,46];
var add = newInt;
data.push(add);
UPDATE: Didn't read the last line to check for duplicates, the best approach I can think of is a loop:
var data = [3434,346,1,6,46];
var add = newInt;
var exists = false;
for (var i = 0; i < input.length; i++) {
if (data[i] == add) {
exists = true;
break;
}
}
if (!exists) {
data.push(add);
// then you would join if you wanted a string
}
You can also use a regular expression:
function appendConditional(s, n) {
var re = new RegExp('(^|\\b)' + n + '(\\b|$)');
if (!re.test(s)) {
return s + (s.length? ',' : '') + n;
}
return s;
}
var nums = '3434,346,1,6,46'
alert( appendConditional(nums, '12') ); // '3434,346,1,6,46,12'
alert( appendConditional(nums, '6') ); // '3434,346,1,6,46'
Oh, since some really like ternary operators and obfustically short code:
function appendConditional(s, n) {
var re = new RegExp('(^|\\b)' + n + '(\\b|$)');
return s + (re.test(s)? '' : (''+s? ',':'') + n );
}
No jQuery, "shims" or cross-browser issues. :-)

Categories

Resources