Automate replace a lot content strings in JavaScript - javascript

I have an string with HTML format, and I need to replace ALL the math exponents in HTML format <sup></sup>, to math exponents without HTML format.
I'm using the replace() method, but I need find and replace 100 exponents, from <sup>1</sup> to <sup>100</sup>, and I should write all the numbers (from 1 to 100).
var copiar = texto.
replace(/<br>/g, "\n").
replace(/<sup><\/sup>/g, "").
replace(/<sup>2<\/sup>/g, "²").
replace(/<sup>3<\/sup>/g, "³").
replace(/<sup>4<\/sup>/g, "⁴").
replace(/<sup>5<\/sup>/g, "⁵").
replace(/<sup>6<\/sup>/g, "⁶").
replace(/<sup>7<\/sup>/g, "⁷").
replace(/<sup>8<\/sup>/g, "⁸").
replace(/<sup>9<\/sup>/g, "⁹").
replace(/<sup>10<\/sup>/g, "¹⁰");
...
replace(/<sup>100<\/sup>/g, "¹⁰⁰");
My question is: There is a way to automate this task? Thanks!
UPDATE: I'm doing this replacements because I'm developing an App for iOS, capable to print (in HTML format) and copy to clipboard (plane text). That's the reason because I'm replacement the <sup> numbers.
UPDATE 14/Oct/2014: I was needing to replace negative exponents too. Using the #minitech answer and modifying a little, I could be able to replace ALL the exponents (positive and negative). Maybe can be useful for someone, here the code:
var map = '⁰¹²³⁴⁵⁶⁷⁸⁹';
var copiar = texto.replace(/<sup>(\-*(\d*))<\/sup>/g, function (str, digits){
return Array.prototype.map.call(digits, function (digit) {
var exp = "";
if (digit != '-') {
exp += map.charAt(digit);
} else {
exp += "¯";
}
return exp;
}).join('');
});

A string and charAt provide a convenient way to map digits to the corresponding superscript digits:
var map = '⁰¹²³⁴⁵⁶⁷⁸⁹';
var copiar = texto.replace(/<sup>(\d*)<\/sup>/g, function (_, digits) {
return Array.prototype.map.call(digits, function (digit) {
return map.charAt(+digit);
}).join('');
});

When you do a replacement, you can supply a function to calculate it, instead of a fixed string. So you can use a pattern for all your <sup> replacements, and use a function that translates the number to Unicode superscripts.
var copiar = texto.
replace(/<br>|<sup>(\d*)<\/sup>/g, function(match, digits) {
if (match == "<br>") {
return "\n";
}
// Rest is for translating superscripts to Unicode
var superdigits = '';
var zero = "0".charCodeAt(0);
var superzero = 0x2070;
var supertwo = 0x00b2;
for (var i = 0; i < digits.length; i++) {
var n = digits.charCodeAt(i) - zero;
var char;
switch (n) {
// Superscripts 2 and 3 are at weird places in Unicode
case 2: case 3:
char = String.fromCharCode(n - 2 + supertwo);
break;
default:
char = String.fromCharCode(n + superzero);
}
superdigits += char;
}
return superdigits;
});

<script>
function get_sup_index(num) {
var new_num = new String(num);
new_num = new_num.replace(/0/g, "⁰").
replace(/1/g, "¹").
replace(/2/g, "²").
replace(/3/g, "³").
replace(/4/g, "⁴").
replace(/5/g, "⁵").
replace(/6/g, "⁶").
replace(/7/g, "⁷").
replace(/8/g, "⁸").
replace(/9/g, "⁹");
return new_num;
}
var my_text = '<sup>1</sup>'+
'<sup>2</sup>'+
'<sup>3</sup>'+
'<sup>4</sup>'+
'<sup>5</sup>'+
'<sup>6</sup>'+
'<sup>7</sup>'+
'<sup>8</sup>'+
'<sup>9</sup>'+
'<sup>10</sup>';
alert(get_sup_index(my_text.replace(/<sup>([0-9]*)<\/sup>/g, "\$1")));
</script>
I hope that can help you.

Related

How do get input 2^3 to Math.pow(2, 3)?

I have this simple calculator script, but it doesn't allow power ^.
function getValues() {
var input = document.getElementById('value').value;
document.getElementById('result').innerHTML = eval(input);
}
<label for="value">Enter: </label><input id="value">
<div id="result">Results</div>
<button onclick="getValues()">Get Results</button>
I tried using input = input.replace( '^', 'Math.pow(,)');
But I do not know how to get the values before '^' and after into the brackets.
Example: (1+2)^3^3 should give 7,625,597,484,987
Use a regular expression with capture groups:
input = '3 + 2 ^3';
input = input.replace(/(\d+)\s*\^\s*(\d+)/g, 'Math.pow($1, $2)');
console.log(input);
This will only work when the arguments are just numbers. It won't work with sub-expressions or when you repeat it, like
(1+2)^3^3
This will require writing a recursive-descent parser, and that's far more work than I'm willing to put into an answer here. Get a textbook on compiler design to learn how to do this.
I don't think you'll be able to do this with simple replace.
If you want to parse infix operators, you build two stacks, one for symbols, other for numbers. Then sequentially walk the formula ignoring everything else than symbols, numbers and closing parenthesis. Put symbols and numbers into their stacks, but when you encounter closing paren, take last symbol and apply it to two last numbers. (was invented by Dijkstra, I think)
const formula = '(1+2)^3^3'
const symbols = []
const numbers = []
function apply(n2, n1, s) {
if (s === '^') {
return Math.pow(parseInt(n1, 10), parseInt(n2, 10))
}
return eval(`${n1} ${s} ${n2}`)
}
const applyLast = () => apply(numbers.pop(), numbers.pop(), symbols.pop())
const tokenize = formula => formula.split(/(\d+)|([\^\/\)\(+\-\*])/).filter(t => t !== undefined && t !== '')
const solver = (formula) => {
const tf = tokenize(formula)
for (let l of formula) {
const parsedL = parseInt(l, 10)
if (isNaN(parsedL)) {
if (l === ')') {
numbers.push(applyLast())
continue
} else {
if (~['+', '-', '*', '/', '^'].indexOf(l))
symbols.push(l)
continue
}
}
numbers.push(l)
}
while (symbols.length > 0)
numbers.push(applyLast())
return numbers.pop()
}
console.log(solver(formula))
Get your input into a string and do...
var input = document.getElementById('value').value;
var values = input.split('^'); //will save an array with [value1, value 2]
var result = Math.pow(values[0], values[1]);
console.log(result);
This only if your only operation is a '^'
EDIT: Saw example after edit, this no longer works.
function getValues() {
var input = document.getElementById('value').value;
// code to make ^ work like Math.pow
input = input.replace( '^', '**');
document.getElementById('result').innerHTML = eval(input);
}
The ** operator can replace the Math.pow function in most modern browsers. The next version of Safari (v10.1) coming out any day supports it.
As said in other answers here, you need a real parser to solve this correctly. A regex will solve simple cases, but for nested statements you need a recursive parser. For Javascript one library that offers this is peg.js.
In your case, the example given in the online version can be quickly extended to handle powers:
Expression
= head:Term tail:(_ ("+" / "-") _ Term)* {
var result = head, i;
for (i = 0; i < tail.length; i++) {
if (tail[i][1] === "+") { result += tail[i][3]; }
if (tail[i][1] === "-") { result -= tail[i][3]; }
}
return result;
}
Term
= head:Pow tail:(_ ("*" / "/") _ Pow)* { // Here I replaced Factor with Pow
var result = head, i;
for (i = 0; i < tail.length; i++) {
if (tail[i][1] === "*") { result *= tail[i][3]; }
if (tail[i][1] === "/") { result /= tail[i][3]; }
}
return result;
}
// This is the new part I added
Pow
= head:Factor tail:(_ "^" _ Factor)* {
var result = 1;
for (var i = tail.length - 1; 0 <= i; i--) {
result = Math.pow(tail[i][3], result);
}
return Math.pow(head, result);
}
Factor
= "(" _ expr:Expression _ ")" { return expr; }
/ Integer
Integer "integer"
= [0-9]+ { return parseInt(text(), 10); }
_ "whitespace"
= [ \t\n\r]*
It returns the expected output 7625597484987 for the input string (1+2)^3^3.
Here is a Python-based version of this question, with solution using pyparsing: changing ** operator to power function using parsing?

Javascript: Cut string after last specific character

I'm doing some Javascript to cut strings into 140 characters, without breaking words and stuff, but now i want the text so have some sense. so i would like if you find a character (just like ., , :, ;, etc) and if the string is>110 characters and <140 then slice it, so the text has more sense. Here is what i have done:
where texto means text, longitud means length, and arrayDeTextos means ArrayText.
Thank you.
//function to cut strings
function textToCut(texto, longitud){
if(texto.length<longitud) return texto;
else {
var cortado=texto.substring(0,longitud).split(' ');
texto='';
for(key in cortado){
if(key<(cortado.length-1)){
texto+=cortado[key]+' ';
if(texto.length>110 && texto.length<140) {
alert(texto);
}
}
}
}
return texto;
}
function textToCutArray(texto, longitud){
var arrayDeTextos=[];
var i=-1;
do{
i++;
arrayDeTextos.push(textToCut(texto, longitud));
texto=texto.replace(arrayDeTextos[i],'');
}while(arrayDeTextos[i].length!=0)
arrayDeTextos.push(texto);
for(key in arrayDeTextos){
if(arrayDeTextos[key].length==0){
delete arrayDeTextos[key];
}
}
return arrayDeTextos;
}
Break the string into sentences, then check the length of the final string before appending each sentence.
var str = "Test Sentence. Test Sentence";
var arr = str.split(/[.,;:]/) //create an array of sentences delimited by .,;:
var final_str = ''
for (var s in arr) {
if (final_str.length == 0) {
final_str += arr[s];
} else if (final_str.length + s.length < 140) {
final_str += arr[s];
}
}
alert(final_str); // should have as many full sentences as possible less than 140 characters.
I think Martin Konecny's solution doesn't work well because it excludes the delimiter and so removes lots of sense from the text.
This is my solution:
var arrTextChunks = text.split(/([,:\?!.;])/g),
finalText = "",
finalTextLength = 0;
for(var i = 0; i < arrTextChunks.length; i += 2) {
if(finalTextLength + arrTextChunks[i].length + 1 < 140) {
finalText += arrTextChunks[i] + arrTextChunks[i + 1];
finalTextLength += arrTextChunks[i].length;
} else if(finalTextLength > 110) {
break;
}
}
http://jsfiddle.net/Whre/3or7j50q/3/
I'm aware of the fact that the i += 2 part does only make sense for "common" usages of punctuation (a single dot, colon etc.) and nothing like "hi!!!?!?1!1!".
Should be a bit more effective without regex splits.
var truncate = function (str, maxLen, delims) {
str = str.substring(0, maxLen);
return str.substring(0, Math.max.apply(null, delims.map(function (s) {
return str.lastIndexOf(s);
})));
};
Try this regex, you can see how it works here: http://regexper.com/#%5E(%5Cr%5Cn%7C.)%7B1%2C140%7D%5Cb
str.match(/^(\r\n|.){1,140}\b/g).join('')

Swap Case on javascript

I made a script that changes the case, but result from using it on text is exactly the same text, without a single change. Can someone explain this?
var swapCase = function(letters){
for(var i = 0; i<letters.length; i++){
if(letters[i] === letters[i].toLowerCase()){
letters[i] = letters[i].toUpperCase();
}else {
letters[i] = letters[i].toLowerCase();
}
}
console.log(letters);
}
var text = 'So, today we have REALLY good day';
swapCase(text);
Like Ian said, you need to build a new string.
var swapCase = function(letters){
var newLetters = "";
for(var i = 0; i<letters.length; i++){
if(letters[i] === letters[i].toLowerCase()){
newLetters += letters[i].toUpperCase();
}else {
newLetters += letters[i].toLowerCase();
}
}
console.log(newLetters);
return newLetters;
}
var text = 'So, today we have REALLY good day';
var swappedText = swapCase(text); // "sO, TODAY WE HAVE really GOOD DAY"
You can use this simple solution.
var text = 'So, today we have REALLY good day';
var ans = text.split('').map(function(c){
return c === c.toUpperCase()
? c.toLowerCase()
: c.toUpperCase()
}).join('')
console.log(ans)
Using ES6
var text = 'So, today we have REALLY good day';
var ans = text.split('')
.map((c) =>
c === c.toUpperCase()
? c.toLowerCase()
: c.toUpperCase()
).join('')
console.log(ans)
guys! Get a little simplier code:
string.replace(/\w{1}/g, function(val){
return val === val.toLowerCase() ? val.toUpperCase() : val.toLowerCase();
});
Here is an alternative approach that uses bitwise XOR operator ^.
I feel this is more elegant than using toUppserCase/ toLowerCase methods
"So, today we have REALLY good day"
.split("")
.map((x) => /[A-z]/.test(x) ? String.fromCharCode(x.charCodeAt(0) ^ 32) : x)
.join("")
Explanation
So we first split array and then use map function to perform mutations on each char, we then join the array back together.
Inside the map function a RegEx tests if the value is an alphabet character: /[A-z]/.test(x) if it is then we use XOR operator ^ to shift bits. This is what inverts the casing of character. charCodeAt convert char to UTF-16 code. XOR (^) operator flips the char. String.fromCharCode converts code back to char.
If RegEx gives false (not an ABC char) then the ternary operator will return character as is.
References:
String.fromCharCode
charCodeAt
Bitwise operators
Ternary operator
Map function
One liner for short mode code wars:
let str = "hELLO wORLD"
str.split("").map(l=>l==l.toLowerCase()?l.toUpperCase():l.toLowerCase()).join("")
const swapCase = (myString) => {
let newString = ''; // Create new empty string
if (myString.match(/[a-zA-Z]/)) { // ensure the parameter actually has letters, using match() method and passing regular expression.
for (let x of myString) {
x == x.toLowerCase() ? x = x.toUpperCase() : x = x.toLowerCase();
newString += x; // add on each conversion to the new string
}
} else {
return 'String is empty, or there are no letters to swap.' // In case parameter contains no letters
}
return newString; // output new string
}
// Test the function.
console.log(swapCase('Work Today Was Fun')); // Output: wORK tODAY wAS fUN
console.log(swapCase('87837874---ABCxyz')); // Output: 87837874---abcXYZ
console.log(swapCase('')); // Output: String is empty, or there are no letters to swap.
console.log(swapCase('12345')); // Output: String is empty, or there are no letters to swap.
// This one will fail. But, you can wrap it with if(typeof myString != 'number') to prevent match() method from running and prevent errors.
// console.log(swapCase(12345));
This is a solution that uses regular expressions. It matches each word-char globally, and then performs a function on that matched group.
function swapCase(letters) {
return letters.replace( /\w/g, function(c) {
if (c === c.toLowerCase()) {
return c.toUpperCase();
} else {
return c.toLowerCase();
}
});
}
#this is a program to convert uppercase to lowercase and vise versa and returns the string.
function main(input) {
var i=0;
var string ='';
var arr= [];
while(i<input.length){
string = input.charAt(i);
if(string == string.toUpperCase()){
string = string.toLowerCase();
arr += string;
}else {
string = string.toUpperCase();
arr += string;
}
i++;
}
console.log(arr);
}
Split the string and use the map function to swap the case of letters.
We'll get the array from #1.
Join the array using join function.
`
let str = 'The Quick Brown Fox Jump Over A Crazy Dog'
let swapedStrArray = str.split('').map(a => {
return a === a.toUpperCase() ? a.toLowerCase() : a.toUpperCase()
})
//join the swapedStrArray
swapedStrArray.join('')
console.log('swapedStrArray', swapedStrArray.join(''))
`
A new solution using map
let swappingCases = "So, today we have REALLY good day";
let swapping = swappingCases.split("").map(function(ele){
return ele === ele.toUpperCase()? ele.toLowerCase() : ele.toUpperCase();
}).join("");
console.log(swapping);
As a side note in addition to what has already been said, your original code could work with just some minor modifications: convert the string to an array of 1-character substrings (using split), process this array and convert it back to a string when you're done (using join).
NB: the idea here is to highlight the difference between accessing a character in a string (which can't be modified) and processing an array of substrings (which can be modified). Performance-wise, Fabricator's solution is probably better.
var swapCase = function(str){
var letters = str.split("");
for(var i = 0; i<letters.length; i++){
if(letters[i] === letters[i].toLowerCase()){
letters[i] = letters[i].toUpperCase();
}else {
letters[i] = letters[i].toLowerCase();
}
}
str = letters.join("");
console.log(str);
}
var text = 'So, today we have REALLY good day';
swapCase(text);

Javascript to test value against regex and later value if needed

in my webpage I have a total in currency format that can either be positive or negative.
Example $5.50 or $(5.50).
This value is nothing other than text contained within a span tag. I'm trying to read the value and convert it into a numeric value in js where I can then perform math calculations against it.
Example $5.50 -> 5.50 and $(5.50) -> -5.50
I have written the following regex script to handle converting negative currency values into numeric values
var regex = /^\$*?\((\d+(\.)?(\d+)?)\)$/
I have the following methods to handle retrieving and converting the value.
//retrieve value from template
$.fn.fieldVal = function () {
var val;
if ($(this).is(':input')) {
val = $(this).val();
} else {
val = $(this).text();
}
return convertCurrencyToNumeric(val);
};
//convert currency to numeric value
function convertCurrencyToNumeric(n) {
var regex = /^\$*?\((\d+(\.)?(\d+)?)\)$/
n = n.replace(/[^0-9-\.]/g, '');
if(isNumber(n)) {
n = parseFloat(n);
return n;
}
return 0;
}
//test if numeric
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
I'm not clear how to first test if the value is negative and secondly if negative, replace the value with regex outcome.
Note: Negating classes can really clear up regEx problems, IMO. And no, I don't care what JSLint's opinion on the matter is. Using '.' is slow and clumsy and the rationale given for that particular lint gotcha is absurd.
function convertCurrency(str){
var negMatch = ( str.match(/(^\$-|^-\$|^$\()/g) ), //handles -$5.05 or $-5.05 too
str = str.replace(/[^\d.]/g,''), //anything that's not a digit or decimal point
//gotcha, Europeans use ',' as a decimal point so there's a localization concern
num = parseFloat(str);
if(negMatch){ num *= -1; }
return num;
}
function getMoney (str) {
var amount = str.replace(/(\$)(\()?(\d+\.\d{0,2})\)?/,
function (match, dollar, neg, money) {
var negSign = neg ? "-" : "";
return negSign + money;
}
);
return parseFloat(amount);
}
var str1 = "$(5.50)";
var str2 = "$5.50";
console.log( getMoney(str1) );
console.log( getMoney(str2) );

how to parse string to int in javascript

i want int from string in javascript how i can get them from
test1 , stsfdf233, fdfk323,
are anyone show me the method to get the integer from this string.
it is a rule that int is always in the back of the string.
how i can get the int who was at last in my string
var s = 'abc123';
var number = s.match(/\d+$/);
number = parseInt(number, 10);
The first step is a simple regular expression - \d+$ will match the digits near the end.
On the next step, we use parseInt on the string we've matched before, to get a proper number.
You can use a regex to extract the numbers in the string via String#match, and convert each of them to a number via parseInt:
var str, matches, index, num;
str = "test123and456";
matches = str.match(/\d+/g);
for (index = 0; index < matches.length; ++index) {
num = parseInt(matches[index], 10);
display("Digit series #" + index + " converts to " + num);
}
Live Example
If the numbers really occur only at the ends of the strings or you just want to convert the first set of digits you find, you can simplify a bit:
var str, matches, num;
str = "test123";
matches = str.match(/\d+/);
if (matches) {
num = parseInt(matches[0], 10);
display("Found match, converts to: " + num);
}
else {
display("No digits found");
}
Live example
If you want to ignore digits that aren't at the end, add $ to the end of the regex:
matches = str.match(/\d+$/);
Live example
var str = "stsfdf233";
var num = parseInt(str.replace(/\D/g, ''), 10);
var match = "stsfdf233".match(/\d+$/);
var result = 0; // default value
if(match != null) {
result = parseInt(match[0], 10);
}
Yet another alternative, this time without any replace or Regular Expression, just one simple loop:
function ExtractInteger(sValue)
{
var sDigits = "";
for (var i = sValue.length - 1; i >= 0; i--)
{
var c = sValue.charAt(i);
if (c < "0" || c > "9")
break;
sDigits = c + sDigits;
}
return (sDigits.length > 0) ? parseInt(sDigits, 10) : NaN;
}
Usage example:
var s = "stsfdf233";
var n = ExtractInteger(s);
alert(n);
This might help you
var str = 'abc123';
var number = str.match(/\d/g).join("");
Use my extension to String class :
String.prototype.toInt=function(){
return parseInt(this.replace(/\D/g, ''),10);
}
Then :
"ddfdsf121iu".toInt();
Will return an integer : 121
First positive or negative number:
"foo-22bar11".match(/-?\d+/); // -22
javascript:alert('stsfdf233'.match(/\d+$/)[0])
Global.parseInt with radix is overkill here, regexp extracted decimal digits already and rigth trimmed string

Categories

Resources