JavaScript - Need help with string manipulation - javascript

say you have:
var foo = "donut [$25]"
What would you need to do in order to delete everything between and including the [ ].
so you get: foo = "donut" after the code is run.
So far I have tried most of the solutions below, but they all either do nothing or crash.
Maybe it's something with my code, please see below:
$('select').change(function () { OnSuccess(mydata); });
function OnSuccess(data) {
var total = 0;
$('select').each(function () {
var sov = parseInt($(this).find('option:selected').attr('value')) || 0; //Selected option value
var sop; //Selected Option Price
for (i = 0; i <= data.length; i++) {
if (data[i].partid == sov) {
sop = data[i].price;
total += sop;
$('#totalprice').html(total);
break;
}
};
//debugger;
$(this).find('option').each(function () {
// $(this).append('<span></span>');
var uov = parseInt($(this).attr('value')) || 0; //Unselected option value
var uop; //Unselected Option Price
for (d = 0; d <= data.length; d++) {
if (data[d].partid == uov) {
uop = data[d].price;
break;
}
}
//debugger;
var newtext = uop - sop;
//{ newtext = "" };
//if (newtext = 0) { newtext.toString; newtext = ""; };
//debugger;
var xtext = $(this).text().toString();
//if (xtext.match(/\[.*\]/) != null) {
xtext.replace(/\s*\[[\s\S]*?\]\s*/g, '').trim();
//}
// var temp = xtext.split('[')[0];
// var temp2 = xtext.split(']')[1];
// resultx = temp + temp2;
if (newtext != 0) {
//xtext.replace(/[.*?]/, "");
$(this).attr("text", xtext + " " + "[" + "$" + newtext + "]");
};
});
});
};

You can also use a regular expression, as Jon Martin pointed out:
var yum = "donut[$25]";
yum.replace(/[.*?]/, ""); // returns "donut"

Alternatively:
var temp = foo.split('[')[0];
var temp2 = foo.split(']')[1];
foo = temp + temp2;

You can use regular expressions (the RegExp() object) to match strings.
var foo = "donut[$25]";
foo.match(/\[.*\]/);
The above will return an array of every item in [square brackets], in this case ["[$25]"].
To just get one result as a string, specify the first index like so:
foo.match(/\[.*\]/)[0];
The above will return "[$25]"
Edit: You know what? I completely misread which bit of the string you're after. This is what you're after:
var foo = "donut[$25]";
foo.match(/\w*/)[0];

How about simply;
var yum = "donut[$25]";
print( yum.substr(0, yum.indexOf("[")) );
>>donut

var begin = foo.search("[");
var end = foo.search("]");
var result = foo.substr(0, begin) + foo.substr(end+1); //Combine anything before [ and after ]
Should be ok right?

Your question leaves unspecified the treatment of the spaces before the [ character, anything after the ], will your string ever contain a linefeed character, multiple occurrences of [..], leading or trailing spaces.
The following will replace all occurrences of 'spaces [ ... ] spaces' with a single space, then it trims the result to remove any leading/trailing spaces.
v.replace (/\s*\[[\s\S]*?\]\s*/g, ' ').trim ();

Related

Counting Words Between Two Variable Strings

Total newbie + first time poster here with very little experience though I feel this problem is one I could solve with the help of some generous strangers.
I am querying a GDoc and attempting to create a function to count words between two strings for two possible end strings, for example:
Example #1
Definitive Title
*Count these words*
===============
OR
Example #2
Definitive Title
*Count these words*
Other words that are in a table
Definitive Title
*Count these other different words*
===============
In both of the above examples I looking to count the words between a pre-defined string and an end string.
If I ran the function that I am trying to create on Example #1 I am hoping it'd return 3 words. For Example #2 I'd hope that my function returns 8 words.
So far my function looks like this:
function doPost(e) {
var docUrl = e.parameter.docUrl
var text = DocumentApp.openByUrl(docUrl).getBody().getText()
var wordCount = text.split(" ").length
return ContentService.createTextOutput(wordCount.toString()).setMimeType(ContentService.MimeType.TEXT)
}
This returns a word count for the entire document. Any advice to point me in the right direction?
For more dynamic, appropriate and accurate solution, execute the following snippets before the split () function. Regular Expressions often used to provide dynamic solutions. It is a must have skill.
text = text.replace(/(^\s*)|(\s*$)/gi,""); // remove the start and end spaces of the string (like trim ())
text = text.replace(/[ ]{2,}/gi," "); // filter out one or more spaces
text = text.replace(/\n /,"\n"); // filter out news lines with spacing at beginning
wordCount = text.split(" ").length;
Here is a solution to your problem you can log the difference of characters and words or you can log the total amount of words or characters in the two sentaces. You are also going to want to put the bigger sentence on top, otherwise it will give you a negative number.
var x = "count these words";
var y = "count words";
function findCharDif(word1, word2) {
var word1length = word1.length;
var word2length = word2.length;
var difference = word1length - word2length;
var total = word1length + word2length;
console.log(difference);
console.log(total);
}
function findWordDif(sentence1, sentence2) {
var words1 = 0;
var words2 = 0;
for (var i = 0; i < sentence1.length; i++) {
if (sentence1[i] == " ") {
words1++;
} else {
continue
}
}
for (var a = 0; a < sentence2.length; a++) {
if (sentence2[a] == " ") {
words2++;
} else {
continue
}
}
var difference = (words1 + 1) - (words2 + 1); // this logs out the difference of words between the sentences
var totalWords = (words1 + 1) + (words2 + 1); // this logs out the total amount of words
console.log(difference);
console.log(totalWords);
}
findCharDif(x, y);
findWordDif(x, y);
The below code seems to have worked! Was able to sit down with someone and solve it with them:
function doPost(e) {
var docUrl = e.parameter.docUrl
/*
var text = DocumentApp.openByUrl(docUrl).getBody().getText()
var wordCount = text.split(" ").length
*/
var wordCount = countScenario2(docUrl);
return ContentService.createTextOutput(wordCount.toString()).setMimeType(ContentService.MimeType.TEXT)
}
/**
* Count the words from Start Test to a table or ====
*/
function countScenario2(docUrl) {
//var docUrl = 'https://docs.google.com/document/d/';
var doc = DocumentApp.openByUrl(docUrl);
var body = doc.getBody();
var reference = body.findText('Start Text');
var start = getIndex('Start Text', body);
var tables = body.getTables();
var count = 0;
for(var j = 1; j < tables.length ; j ++) {
var end = body.getChildIndex(tables[j]);
for (var i = start + 1; i < end; i++) {
var element = body.getChild(i);
var text = element.getText();
//if(text.length > 0) count += text.split(" ").filter(word => word !== ' ' && word !== '' && word !== ' ').length;
var match = text.match(/\b(\w+)\b/g);
count += (match) ? match.length : 0;
}
console.log(count);
var reference = body.findText('Start Text', reference);
var element = reference.getElement();
var start = body.getChildIndex(element.getParent());
}
var end = getIndex('=========================================================', body);
for (var i = start + 1; i < end; i++) {
var element = body.getChild(i);
var text = element.getText();
//if(text.length > 0) count += text.split(" ").filter(word => word !== ' ' && word !== '' && word !== ' ').length;
var match = text.match(/\b(\w+)\b/g);
count += (match) ? match.length : 0;
}
console.log(count);
return count ;
}
/**
* This will return the index of the element
*
* #param {string} keyword The text to be found
* #param {Body} body This is the body of the document
*/
function getIndex(keyword, body, previous) {
var reference = body.findText(keyword, previous);
var element = reference.getElement();
return body.getChildIndex(element.getParent());
}
/************ */
function testPost(){
var e = {parameter:{docUrl:'https://docs.google.com/document/d/'}};
var result = doPost(e);
console.log(JSON.stringify(result.getContent()));}
/**
* Count the words from Start Text to ====
*/
function countScenario1(docUrl) {
//var docUrl = 'https://docs.google.com/document/d/';
var doc = DocumentApp.openByUrl(docUrl);
var body = doc.getBody();
var start = getIndex('Start Text', body);
var end = getIndex('=========================================================', body);
var count = 0;
for (var i = start + 1; i < end; i++) {
var element = body.getChild(i);
var text = element.getText();
//if(text.length > 0) count += text.split(" ").filter(word => word !== ' ' && word !== '' && word !== ' ').length;
var match = text.match(/\b(\w+)\b/g);
count += (match) ? match.length : 0;
}
console.log(count);
return count;
}
function test(){
var docUrl = 'https://docs.google.com/document/d/';
var wordCount = countScenario2(docUrl);
console.log(wordCount);
}
As what #Rishabh K said in his answer, you should definitely want to replace trailing spaces and multiple spaces to avoid inaccurate results.
However on the other hand, I don't think it answers the OP's question. Correct me if I'm wrong but I think this is what you want:
var sample1 = `This is the start identifier
These words should be included
As well As these ones
Even this
Until it ends
now
Ending identifier
These words shouldn't be included
If any of these appears, the logic is wrong`;
var sample2 = sample1 + `
This is the start identifier
These some few words
should also be included in the result set
Ending identifier`;
var sample3 = sample2 + `
This is the start identifier
Although we have the start identifier above
These words shouldn't be included
because there is no corresponding end identifier`;
function getWordDiffBetween(source, str1, str2) {
// make sure newSource, str1 and str2 are all strings
var args = Array.prototype.slice.call(arguments);
args.forEach(function(str, idx) {
if (typeof str !== 'string') {
throw `Argument ${[idx + 1]} is not a string.`;
}
});
var startId = '<==start==>',
endId = '<==end==>';
var newSource = source.replace(new RegExp(str1, 'g'), startId) // replace the start identifier with our own
.replace(new RegExp(str2 + '|={2,}', 'g'), endId) // replace the end identifier with our own
.replace(/(^\s*)|(\s*$)/gi, "") // remove the start and end spaces of the string (like trim ())
.replace(/\s+/g, ' ') //replace all 1 or more spaces/newline/linefeed with a single space
//separate text into words which are separated by a space since we replaced all newlines with space
var words = newSource.split(' ');
// get the indexes where the start and end identifiers occured
var strOneIdx = getAllIndexes(words, startId, true);
var strTwoIdx = getAllIndexes(words, endId, true);
var results = [], // we will store our results here
i;
for (i = 0; i < strOneIdx.length; i++) {
var idxOne = strOneIdx[i]; // current index for str1
var idxTwo = strTwoIdx.find(x => x > idxOne);
//make sure that idxOne has a partner
if (idxTwo) {
var wordsInBetween = words.slice(idxOne + 1, idxTwo); //get range between idxOne and idxTwo
results = results.concat(wordsInBetween); // add the result
}
}
return results;
}
function getAllIndexes(arr, val) {
var indexes = [],
i;
for (i = 0; i < arr.length; i++) {
if (arr[i] === val) {
indexes.push(i);
}
}
return indexes;
}
var startIdentifier = 'This is the start identifier',
endIdentifier = 'Ending identifier',
wordResults = {
sample1: getWordDiffBetween(sample1, startIdentifier, endIdentifier),
sample2: getWordDiffBetween(sample2, startIdentifier, endIdentifier),
sample3: getWordDiffBetween(sample3, startIdentifier, endIdentifier) //should be equal to sample2
};
console.log(wordResults);
We have 2 functions - getWordDiffBetween and getAllIndexes. For explanation, check the comments I added in noteworthy lines.
Edit (updated snippet above):
It seems like you also want "====================" included as your end identifier. This can be done by changing the code:
.replace(new RegExp(str2, 'g'), endId) // replace the end identifier with our own
into
.replace(new RegExp(str2 + '|={2,}', 'g'), endId) // replace the end identifier with our own
which means match occurence of your <end string> or if there is 2 or more occurences of =. You can also change the number 2 in {2,} to your desired count.

Group regex is missing last match

as given in sample code fstr need match all occurence of regEx_C and need to replace with some dynamic value. and make sure each match should have unique value.
in this sample fstr.match(regEX_C) matches 4 match and i need to replace with 1 dynamic value for each.
var_Viablecells_C = X
var_IVCC_C = Y
var_Viablecells_C = Z
var_IVCC_C = Z1
the value assigned should not match with anyone.
var fstr = '(Math.log(var_Viablecells_C-var_Viablecells_P)/(2-1)+ var_IVCC_C + var_Viablecells_C / var_IVCC_C)';
var regEx_C = /var_(\w+)_C/ig;
var c_val = 5.5;
function putExpValForRegExMatch(fstr, regEx, val) {
var all_match = fstr.match(regEx);
if (null == all_match) return fstr;
console.log(all_match);
for (var i = 0; i < all_match.length; i++) {
console.log(i);
console.log(fstr);
var current_match = regEx.exec(fstr);
if (current_match == null) return fstr;
console.log(current_match);
fstr = replaceRange(fstr, current_match.index, current_match.index + current_match[0].length - 1, '');
fstr = replaceAt(fstr, current_match.index, val);
console.log(fstr);
}
return fstr;
}
function replaceAt(string, index, replace) {
return string.substring(0, index) + replace + string.substring(index + 1);
}
function replaceRange(s, start, end, substitute) {
return s.substring(0, start) + substitute + s.substring(end);
}
console.log(putExpValForRegExMatch(fstr, regEx_C, c_val));
You can just use string.prototype.replace()
var fstr = '(Math.log(var_Viablecells_C-var_Viablecells_P)/(2-1)+ var_IVCC_C + var_Viablecells_C / var_IVCC_C)';
var regEx_C = /var_(\w+)_C/ig;
var c_val = 5.5;
output = fstr.replace(regEx_C,c_val)

How to get parameter value inside a string?

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

I need to get the last two value after dot using javascript split

I am getting the results like demo.in,demo.co.in,demo.tv,demo.org.in
I need to split the extension separately using JavaScript split function
var vsp = i.split(".");
this is my code I will get the result as
demo,in demo,co,in
but I need to get the extension separately
Working fiddle(demo version)
var values = [
"demo.in",
"demo.co.in",
"demo.tv","demo.org"
];
var results = [];
// iterate through the values
for (var i = 0, len = values.length; i < len; i++) {
// Split the parts on every dot.
var parts = values[i].split(".");
// Remove the first part (before the first dot).
parts = parts.slice(1, parts.length);
// Join the results together
results.push(parts.join("."));
};
console.dir(results); // all done
// Nicely display the values for the OP:
for (var i = 0, len = results.length; i < len; i++) {
document.body.innerHTML += (i + 1) + ": " + results[i] + "<br />";
};
I have no idea what you want, so here's some functions to cover the likely cases:
var s = 'demo.co.in'
// Return everything before the first '.'
function getExtension(s) {
var m = s.match(/^[^.]+/);
return m? m[0] : '';
}
alert(getExtension(s)); // demo
// Return everything after the last '.'
function getExtension2(s) {
var m = s.match(/[^.]+$/);
return m? m[0] : '';
}
alert(getExtension2(s)); // in
// Return everything after the first '.'
function getExtension3(s) {
return s.replace(/^[^.]+\./, '');
}
alert(getExtension3(s)); // co.in
I could not understand exactly .. "the extension" . You can try like below code
var urls = "demo,demo.in,my.demo.co.in,demo.tv,demo.org.in"
.split(',');
var splited = urls.reduce( function( o, n ){
var parts = n.split( '.' );
o[ n ] = (function(){
var ext = [];
while( !(parts.length == 1 || ext.length == 2) ) {
ext.unshift( parts.pop() );
};
return ext.join('.');
}());
return o;
}, {} );
console.log( JSON.stringify( splited ) );
which prints
{
"demo":"",
"demo.in":"in",
"my.demo.co.in":"co.in",
"demo.tv":"tv",
"demo.org.in":"org.in"
}
process result using
for( var i in splited ) {
console.log( i, splited[i]);
}
Try this:
var vsp = i.split(".");
for(var i=0; i< vsp.length; i++){
if(i !== 0){ //leaving the first match
// do something with vsp[i]
}
}
I hope you are not considering www also. :). If so, then keep i>1 instead of i !== 0.
There are several ways to do it (probably none as easy as it should be). You could define a function like this:
function mySplit(str, delim) {
var idx = (str.indexOf(delim) == -1) ? str.indexOf(delim) : str.length;
return [str.substr(0,idx), str.substr(idx)];
}
And then call it like: var sp = mySplit(i, ".");
You can also use lastIndexOf, which returns the location of the last . and from there you can get the rest of the string using substring.
function getExtension(hostName) {
var extension = null;
if(hostName && hostName.length > 0 && hostName.indexOf(".") !== -1) {
extension = hostName.substring(hostName.lastIndexOf(".") + 1);
}
return extension;
}
From there, you can use this function in a loop to get the extensions of many host names.
Edit Just noticed the "last two values" part in the title :) Thanks #rab

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