Try to implement a simple text parser in javascript - javascript

i´m trying to bring a simple text parser from Java to Javascript.
The requierement is to transform a given csv file in to another format. The original file list a number of values according to one id in certain lines:
for example:
11111; 12; 23; 23 ;....
11111; 32; 12; 12 ;....
So the first value is an Id and the other values are according to this Id.
Now I need the same file with alle the values according to the one Id in a single line.
the result should be something like:
11111;12; 23; 23; 32; 12; 12 ;....
I already achieved this with a simple Java class:
public static void main(String[] args) throws Exception {
PrintWriter writer = new PrintWriter("t2_lines.csv", "UTF-8");
BufferedReader br = new BufferedReader(new FileReader("t2.csv"));
String previousId="";
String line;
while ((line = br.readLine()) != null) {
String [] words = line.split(";");
String id = words[0];
if (previousId.equals(id)){
// the loop starts at 4 to cut out some unneded values
for(int i=4;i<words.length;i++) {
writer.print(words[i]+";");
}
}else{
writer.println("");
for(String word : words)
writer.print(word+";");
previousId = id;
}
}
br.close();
writer.close();
}
and now I try to rebuild this thing in Javascript by read in a file from the client and present the result in a textfield - but unfortunately i´ve never implemented anything in Javascript before...
This is my approach so far:
window.onload = function () {
var fileInput = document.getElementById('fileInput');
var origFileDisplayArea = document.getElementById('origFileDisplayArea');
var reformatFileDisplayArea= document.getElementById('reformatFileDisplayArea');
fileInput.addEventListener('change', function (e) {
var file = fileInput.files[0];
var textType = /text.*/;
if (file.type.match(textType)) {
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function (e) {
var result = reader.result;
var table = parse(result);
origFileDisplayArea.innerText = table;
}
} else {
origFileDisplayArea.innerText = "File not supported!"
}
});
}
function parse(input) {
var previousId = "";
var table = "";
if (typeof input !== "undefined")
var lines = input.split("\n");
for (var i = 0; i <= lines.length; i++) {
var line = lines[i];
if (typeof line !== "undefined")
var words = line.split(";");
console.log("words length: ", words.length);
for (var j = 0; j <= words.length; j++ ) {
var word = words[j];
if (typeof word !== "undefined") {
word.toString();
var id = words[0];
if (previousId === id) {
for (var jj = 4; jj <=words.length; jj++){
console.log("jj: " + jj)
table += words[jj]+";";
}
}else {
table += "\n";
for (var word in words) {
table += word + ";";
previousId = id;
}
}
}
}
}
return table;
}
But unfortunately i´m stucked now with undefined values and the whole thing took ages to run.
So any hints/help would be greatly appreciated.
Thanks in advance

Yes for the FileReader, I can't see a way to avoid that in this context. That doesn't look like where you have the problem.
As for parse, the split method can use up a lot of memory so I'd avoid using it on the whole file, and for..in is not designed for looping over an Array.
function parse(str_in) {
var i = -1, j = -1,
str_out = '',
last_id = '',
words;
str_in += '\n'; // not sure if necessary - let the last line pass `while`
// loop by seeking out the next new line
// i = old_index + 1
// j = next \n after old_index
// .slice(i, j) gives just the line
while (-1 !== (j = str_in.indexOf('\n', i = j + 1))) {
words = str_in.slice(i, j).split(';')
// loop words to trim whitespace here if you want
if (last_id === words[0]) // throw away first item if on the same id
words = words.slice(1);
else {
last_id = words[0];
if (str_out.length) // lazy prevent first char newline
str_out += '\n';
}
str_out += words.join(';'); // if you trimmed witespace, re-add here
// if you don't have a final semicolon, add it too
}
return str_out;
}
Now
parse('11111; 12; 23; 23 ;\n11111; 32; 12; 12 ;');
// "11111; 12; 23; 23 ; 32; 12; 12 ;"
Alternatively, you might find it easier to write methods similar to what you're used to in Java so you can work with minimal changes, e.g.
function ReadLineGenerator(text) {
var start = -1, end = -1;
return function readLine() {
if (end < start) {
start = end = -1;
return null;
}
start = end + 1;
end = text.indexOf('\n', start);
if (end !== -1)
return text.slice(start, end);
else
return text.slice(start);
};
}
// example usage
var str = 'a\nb\nc',
f = ReadLineGenerator(str),
line;
while (null !== (line = f()))
console.log(line);
// "a", "b", "c" logged
// line === null

Related

How can I extract all contained characters in a String? [duplicate]

I have a string with repeated letters. I want letters that are repeated more than once to show only once.
Example input: aaabbbccc
Expected output: abc
I've tried to create the code myself, but so far my function has the following problems:
if the letter doesn't repeat, it's not shown (it should be)
if it's repeated once, it's show only once (i.e. aa shows a - correct)
if it's repeated twice, shows all (i.e. aaa shows aaa - should be a)
if it's repeated 3 times, it shows 6 (if aaaa it shows aaaaaa - should be a)
function unique_char(string) {
var unique = '';
var count = 0;
for (var i = 0; i < string.length; i++) {
for (var j = i+1; j < string.length; j++) {
if (string[i] == string[j]) {
count++;
unique += string[i];
}
}
}
return unique;
}
document.write(unique_char('aaabbbccc'));
The function must be with loop inside a loop; that's why the second for is inside the first.
Fill a Set with the characters and concatenate its unique entries:
function unique(str) {
return String.prototype.concat.call(...new Set(str));
}
console.log(unique('abc')); // "abc"
console.log(unique('abcabc')); // "abc"
Convert it to an array first, then use Josh Mc’s answer at How to get unique values in an array, and rejoin, like so:
var nonUnique = "ababdefegg";
var unique = Array.from(nonUnique).filter(function(item, i, ar){ return ar.indexOf(item) === i; }).join('');
All in one line. :-)
Too late may be but still my version of answer to this post:
function extractUniqCharacters(str){
var temp = {};
for(var oindex=0;oindex<str.length;oindex++){
temp[str.charAt(oindex)] = 0; //Assign any value
}
return Object.keys(temp).join("");
}
You can use a regular expression with a custom replacement function:
function unique_char(string) {
return string.replace(/(.)\1*/g, function(sequence, char) {
if (sequence.length == 1) // if the letter doesn't repeat
return ""; // its not shown
if (sequence.length == 2) // if its repeated once
return char; // its show only once (if aa shows a)
if (sequence.length == 3) // if its repeated twice
return sequence; // shows all(if aaa shows aaa)
if (sequence.length == 4) // if its repeated 3 times
return Array(7).join(char); // it shows 6( if aaaa shows aaaaaa)
// else ???
return sequence;
});
}
Using lodash:
_.uniq('aaabbbccc').join(''); // gives 'abc'
Per the actual question: "if the letter doesn't repeat its not shown"
function unique_char(str)
{
var obj = new Object();
for (var i = 0; i < str.length; i++)
{
var chr = str[i];
if (chr in obj)
{
obj[chr] += 1;
}
else
{
obj[chr] = 1;
}
}
var multiples = [];
for (key in obj)
{
// Remove this test if you just want unique chars
// But still keep the multiples.push(key)
if (obj[key] > 1)
{
multiples.push(key);
}
}
return multiples.join("");
}
var str = "aaabbbccc";
document.write(unique_char(str));
Your problem is that you are adding to unique every time you find the character in string. Really you should probably do something like this (since you specified the answer must be a nested for loop):
function unique_char(string){
var str_length=string.length;
var unique='';
for(var i=0; i<str_length; i++){
var foundIt = false;
for(var j=0; j<unique.length; j++){
if(string[i]==unique[j]){
foundIt = true;
break;
}
}
if(!foundIt){
unique+=string[i];
}
}
return unique;
}
document.write( unique_char('aaabbbccc'))
In this we only add the character found in string to unique if it isn't already there. This is really not an efficient way to do this at all ... but based on your requirements it should work.
I can't run this since I don't have anything handy to run JavaScript in ... but the theory in this method should work.
Try this if duplicate characters have to be displayed once, i.e.,
for i/p: aaabbbccc o/p: abc
var str="aaabbbccc";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 ){
return obj;
}
}
).join("");
//output: "abc"
And try this if only unique characters(String Bombarding Algo) have to be displayed, add another "and" condition to remove the characters which came more than once and display only unique characters, i.e.,
for i/p: aabbbkaha o/p: kh
var str="aabbbkaha";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 && str.lastIndexOf(obj,i-1)==-1){ // another and condition
return obj;
}
}
).join("");
//output: "kh"
<script>
uniqueString = "";
alert("Displays the number of a specific character in user entered string and then finds the number of unique characters:");
function countChar(testString, lookFor) {
var charCounter = 0;
document.write("Looking at this string:<br>");
for (pos = 0; pos < testString.length; pos++) {
if (testString.charAt(pos) == lookFor) {
charCounter += 1;
document.write("<B>" + lookFor + "</B>");
} else
document.write(testString.charAt(pos));
}
document.write("<br><br>");
return charCounter;
}
function findNumberOfUniqueChar(testString) {
var numChar = 0,
uniqueChar = 0;
for (pos = 0; pos < testString.length; pos++) {
var newLookFor = "";
for (pos2 = 0; pos2 <= pos; pos2++) {
if (testString.charAt(pos) == testString.charAt(pos2)) {
numChar += 1;
}
}
if (numChar == 1) {
uniqueChar += 1;
uniqueString = uniqueString + " " + testString.charAt(pos)
}
numChar = 0;
}
return uniqueChar;
}
var testString = prompt("Give me a string of characters to check", "");
var lookFor = "startvalue";
while (lookFor.length > 1) {
if (lookFor != "startvalue")
alert("Please select only one character");
lookFor = prompt(testString + "\n\nWhat should character should I look for?", "");
}
document.write("I found " + countChar(testString, lookFor) + " of the<b> " + lookFor + "</B> character");
document.write("<br><br>I counted the following " + findNumberOfUniqueChar(testString) + " unique character(s):");
document.write("<br>" + uniqueString)
</script>
Here is the simplest function to do that
function remove(text)
{
var unique= "";
for(var i = 0; i < text.length; i++)
{
if(unique.indexOf(text.charAt(i)) < 0)
{
unique += text.charAt(i);
}
}
return unique;
}
The one line solution will be to use Set. const chars = [...new Set(s.split(''))];
If you want to return values in an array, you can use this function below.
const getUniqueChar = (str) => Array.from(str)
.filter((item, index, arr) => arr.slice(index + 1).indexOf(item) === -1);
console.log(getUniqueChar("aaabbbccc"));
Alternatively, you can use the Set constructor.
const getUniqueChar = (str) => new Set(str);
console.log(getUniqueChar("aaabbbccc"));
Here is the simplest function to do that pt. 2
const showUniqChars = (text) => {
let uniqChars = "";
for (const char of text) {
if (!uniqChars.includes(char))
uniqChars += char;
}
return uniqChars;
};
const countUnique = (s1, s2) => new Set(s1 + s2).size
a shorter way based on #le_m answer
let unique=myArray.filter((item,index,array)=>array.indexOf(item)===index)

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.

Ignoring punctuation in JavaScript

I am working on a Caeser cipher encryptor with JavaScript for a university project and have so far managed to get it working fine.
The only problem is, I need to retain the punctuation ( ,!, ? etc) after encryption and I'm having difficulties. Here is my current code:
function encryptor() {
var alphabet = "abcdefghijklmnopqrstuvwxyz";
var letter = "";
var encWord = "";
var userInput = document.getElementById("message").value;
var key = parseInt(window.prompt("Enter a key:"));
for (i = 0; i < userInput.length; i++) {
letter = userInput[i];
var shift = alphabet.indexOf(letter);
if (letter.match("/[^A-Za-z0-9_]/")) {
continue;
} else if (shift < 23) {
var encLetter = alphabet[shift + key];
} else {
var encLetter = alphabet[shift - (26 - key)];
}
encWord += encLetter;
}
document.getElementById("encWord").innerHTML = encWord;
}
Could anyone please point me in the right direction please?
Thanks.
Before the continue you should add letter to encWord
if (letter.match(/[^A-Za-z0-9_]/)) {
encWord += letter;
continue;
}
Otherwise it will just skip it.
For keepint the punctuation, you could check, if the character is in the alphabe string and if not, then use the punctuation for this item.
function encryptor() {
var alphabet = "abcdefghijklmnopqrstuvwxyz",
letter,
encWord = "",
userInput = document.getElementById('message').value,
key = parseInt(window.prompt("Enter a key:")),
shift,
i;
for (i = 0; i < userInput.length; i++) {
letter = userInput[i];
shift = alphabet.indexOf(letter);
if (shift === -1) {
encWord += letter;
continue;
}
encWord += alphabet[(shift + key) % alphabet.length];
}
document.getElementById("encWord").innerHTML = encWord;
}
<input id="message" type="text" onchange="encryptor()"><br>
<div id="encWord"></div>
The easiest method would be to maintain an "alphabet" and simply shift along it, using indexOf to get each symbols location.
Here is an implementation:
var caesarCipher = (function() {
var alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#¤%&/()=?`½§#£$€{[]}|\'*';
return function caesarCipher(message, offset) {
if (offset === void 0) {
offset = 1;
}
return message.replace(/./igm, function(letter) {
if (alphabet.indexOf(letter) >= 0) {
return alphabet[((alphabet.indexOf(letter) + offset) + alphabet.length) % alphabet.length];
}
return letter;
});
};
})();
//TEST
var chipherOffset = 7;
var message = "Hello World.";
caesarCipher(message, chipherOffset);
console.log(caesarCipher(message, chipherOffset));
console.log(caesarCipher(caesarCipher(message, chipherOffset), 0 - chipherOffset));
Notice how i "forgot" to add . to my alphabet. That is the risk you run when maintaining your own alphabet.
Another solution would be to use charCodeAt and String.fromCharCode and simply use the build-in alphabet already in the browser:
var caesarCipher = (function () {
var alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#¤%&/()=?`½§#£$€{[]}|\'*';
return function caesarCipher(message, offset) {
if (offset === void 0) { offset = 1; }
return message.replace(/./igm, function (letter) {
return String.fromCharCode(letter.charCodeAt(0) + offset);
});
};
})();
//TEST
var chipherOffset = 7;
var message = "Hello World.";
caesarCipher(message, chipherOffset);
console.log(caesarCipher(message, chipherOffset));
console.log(caesarCipher(caesarCipher(message, chipherOffset), 0 - chipherOffset));
This solution fixes the "forgot-to-add-symbol" issue, but you risk getting some very weird symbols like "\n", which can really mess your strings up!

Perform a merge on two strings

I'm trying to build a collaborative doc editor and implement operational transformation. Imagine we have a string that is manipulated simultaneously by 2 users. They can only add characters, not remove them. We want to incorporate both of their changes.
The original string is: catspider
The first user does this: cat<span id>spider</span>
The second user does this: c<span id>atspi</span>der
I'm trying to write a function that will produce: c<span id>at<span id>spi</span>der</span>
The function I've written is close, but it produces c<span id>at<span i</span>d>spider</span> codepen here
String.prototype.splice = function(start, newSubStr) {
return this.slice(0, start) + newSubStr + this.slice(start);
};
function merge(saved, working, requested) {
if (!saved || !working || !requested) {
return false;
}
var diffSavedWorking = createDiff(working, saved);
var diffRequestedWorking = createDiff(working, requested);
var newStr = working;
for (var i = 0; i < Math.max(diffRequestedWorking.length, diffSavedWorking.length); i++) {
//splice does an insert `before` -- we will assume that the saved document characters
//should always appear before the requested document characters in this merger operation
//so we first insert requested and then saved, which means that the final string will have the
//original characters first.
if (diffRequestedWorking[i]) {
newStr = newStr.splice(i, diffRequestedWorking[i]);
//we need to update the merge arrays by the number of
//inserted characters.
var length = diffRequestedWorking[i].length;
insertNatX(diffSavedWorking, length, i + 1);
insertNatX(diffRequestedWorking, length, i + 1);
}
if (diffSavedWorking[i]) {
newStr = newStr.splice(i, diffSavedWorking[i]);
//we need to update the merge arrays by the number of
//inserted characters.
var length = diffSavedWorking[i].length;
insertNatX(diffSavedWorking, length, i + 1);
insertNatX(diffRequestedWorking, length, i + 1);
}
}
return newStr;
}
//arr1 should be the shorter array.
//returns inserted characters at their
//insertion index.
function createDiff(arr1, arr2) {
var diff = [];
var j = 0;
for (var i = 0; i < arr1.length; i++) {
diff[i] = "";
while (arr2[j] !== arr1[i]) {
diff[i] += arr2[j];
j++;
}
j++;
}
var remainder = arr2.substr(j);
if (remainder) diff[i] = remainder;
return diff;
}
function insertNatX(arr, length, pos) {
for (var j = 0; j < length; j++) {
arr.splice(pos, 0, "");
}
}
var saved = 'cat<span id>spider</span>';
var working = 'catspider';
var requested = 'c<span id>atspi</span>der';
console.log(merge(saved, working, requested));
Would appreciate any thoughts on a better / simpler way to achieve this.

JavaScript - Need help with string manipulation

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 ();

Categories

Resources