Replace text surrounded by *** with <b> and </b> - actionscript-3

Let's say I have a string
var myString: String = "This ***is*** my ***string***"
Now I'm searching for a way to replace the stars with html-bold tags.
After replacement the code should look like:
"This <b>is</b> my <b>string</b>
What I've done so far:
var boldPattern : RegExp = /\*\*\*.*?\*\*\*/;
while(boldPattern.test(goalOv[gCnt][1])){
myString = myString.replace(boldPattern, "<b>"+myString+"</b>");
}
This ends up with an endless Loop (because I'm assigning the string to itself).
Thanks

I'm not good at regular expressions, but I think this simple solution will do the trick:
var boldPattern : RegExp = /(\*\*\*)/;
var myString: String = "This ***is*** my ***string***";
var count:int = 0;
while(boldPattern.test(myString))
{
if(count % 2 == 1)
myString = myString.replace(boldPattern, "</b>");
else
myString = myString.replace(boldPattern, "<b>");
count++;
}

As Gio said, that looping isn't the best way of replacing globally. You should instead do the following to avoid looping and have replacement in one pass over the string.
var boldPattern :String = "This ***is*** my ***string***";
var myString:RegExp = /\*\*\*([^*]*)\*\*\*/g;
var replText:String = "<b>$1</b>";
myString = myString.replace(boldPattern, replText);
Also, if you want to do it more correctly to allow for myString have have string of 1 or 2 *, you can use:
/\*\*\*(([^*]+\*{0,2})+)\*\*\*/g

Related

Script that would find and mark the same words in the paragraph

I'm a fiction writer and I used to do my writing in MS Word. I've written some macros to help me edit the fiction text and one of them check the paragraph and marks (red) the duplicate (or triplicate words, etc). Example:
"I came **home**. And while at **home** I did this and that."
Word "home" is used twice and worth checking if I really can't change the sentence.
Now I mostly use google documents for writing, but I still have to do my editing in MS Word, mostly just because of this macro - I am not able to program it in the google script.
function PobarvajBesede() {
var doc = DocumentApp.getActiveDocument();
var cursor = DocumentApp.getActiveDocument().getCursor();
var surroundingText = cursor.getSurroundingText().getText();
var WordsString = WORDS(surroundingText);
Logger.log(WordsString);
//so far, so good. But this doesn't work:
var SortedWordsString = SORT(WordsString[1],1,False);
// and I'm lost.
}
function WORDS(input) {
var input = input.toString();
var inputSplit = input.split(" ");
// Logger.log(inputSplit);
inputSplit = inputSplit.toString();
var punctuationless = inputSplit.replace(/[.,\/#!$%\?^&\*;:{}=\-_`~()]/g," ");
var finalString = punctuationless.replace(/\s{2,}/g," ");
finalString = finalString.toLowerCase();
return finalString.split(" ") ;
}
If I could only get a list of words (in uppercase, longer than 3 characters), sorted by the number of their appearances in the logger, it would help me a lot:
HOME (2)
AND (1)
...
Thank you.
Flow:
Transform the string to upper case and sanitize the string of all non ascii characters
After splitting the string to word array, reduce the array to a object of word:count
Map the reduced object to a 2D array [[word,count of this word],[..],...] and sort the array by the inner array's count.
Snippet:
function wordCount(str) {
str = str || 'I came **home**. And while at **home** I did this and that.';
var countObj = str
.toUpperCase() //'I CAME **HOME**...'
.replace(/[^A-Z ]/g, '') //'I CAME HOME...'
.split(' ') //['I', 'CAME',..]
.reduce(function(obj, word) {
if (word.length >= 3) {
obj[word] = obj[word] ? ++obj[word] : 1;
}
return obj;
}, {}); //{HOME:2,DID:1}
return Object.keys(countObj)
.map(function(word) {
return [word, countObj[word]];
}) //[['HOME',2],['CAME',1],...]
.sort(function(a, b) {
return b[1] - a[1];
});
}
console.info(wordCount());
To read and practice:
Object
Array methods
This is a combination of TheMaster answer and some of my work. I need to learn more about the way he did it so I spent some learning time today. This function eliminates some problems I was having the carriage returns and it also removes items that only appear once. You should probably pick TheMasters solution as I couldn't have done it without his work.
function getDuplicateWords() {
var str=DocumentApp.getActiveDocument().getBody().getText();
var countObj = str
.toUpperCase()
.replace(/\n/g,' ')
.replace(/[^A-Z ]/g, '')
.split(' ')
.reduce(function(obj, word) {
if (word.length >= 2) {
obj[word] = obj[word] ? ++obj[word] : 1;
}
return obj;
}, {});
var oA=Object.keys(countObj).map(function(word){return [word, countObj[word]];}).filter(function(elem){return elem[1]>1;}).sort(function(a,b){return b[1]-a[1]});
var userInterface=HtmlService.createHtmlOutput(oA.join("<br />"));
DocumentApp.getUi().showSidebar(userInterface);
}
function onOpen() {
DocumentApp.getUi().createMenu('MyMenu')
.addItem('Get Duplicates','getDuplicateWords' )
.addToUi();
}
And yes I was having problems with get the results to change in my last solution.

Read a string in AS3

I have a question regarding to my project which is how to read a string in AS3.
Actually, I have an text file named test.txt. For instance:
It consists of:
Sun,Mon,Tue,Wed,Thu,Fri,Sat
and then I want to put all of them into an array and then a string to show them in the dynamic text Box called text_txt:
var myTextLoader:URLLoader = new URLLoader();
myTextLoader.addEventListener(Event.COMPLETE, onLoaded);
function onLoaded(e:Event):void
{
var days:Array = e.target.data.split(/\n/);
var str:String;
stage.addEventListener(MouseEvent.CLICK, arrayToString);
function arrayToString(e:MouseEvent):void
{
for (var i=0; i<days.length; i++)
{
str = days.join("");
text_txt.text = str + "\n" + ";"; //it does not work here
}
}
}
myTextLoader.load(new URLRequest("test.txt"));
BUT IT DOES NOT show them in different line and then put a ";" at the end of each line !
I can make it to show them in different line, but I need to put them in different line in txt file and also I still do not get the ";" at the end of each line unless put it in the next file also at the end of each line.
And then I want to read the string and show an object from my library based on each word or line. for example:
//I do not know how to write it or do we have a function to read a string and devide it to the words after each space or line
if (str.string="sun"){
show(obj01);
}
if (str.string="mon"){
show(obj02);
}
I hope I can get the answer for this question.
Please inform me if you can not get the concept of the last part. I will try to explain it more until you can help me.
Thanks in advance
you must enable multiline ability for your TextField (if did not)
adobe As3 DOC :
join() Converts the elements in an array to strings, inserts the
specified separator between the elements, concatenates them, and
returns the resulting string. A nested array is always separated by a
comma (,), not by the separator passed to the join() method.
so str = days.join(""); converts the Array to a single string, and as your demand ( parameter passed to join is empty "") there is no any thing between fetched lines. and text_txt.text = str + "\n" + ";"; only put a new line at the end of the text once.
var myTextLoader:URLLoader = new URLLoader();
var days:Array;
myTextLoader.addEventListener(Event.COMPLETE, onLoaded);
function onLoaded(e:Event):void
{
days = e.target.data.split(/\n/);
var str:String;
stage.addEventListener(MouseEvent.CLICK, arrayToString);
}
myTextLoader.load(new URLRequest("test.txt"));
function arrayToString(e:MouseEvent):void
{
text_txt.multiline = true;
text_txt.wordWrap = true;
text_txt.autoSize = TextFieldAutoSize.LEFT;
text_txt.text = days.join("\n");
}
also i moved arrayToString out of onLoaded
for second Question: to checking existance of a word, its better using indexOf("word") instead comparing it with "==" operator, because of invisible characters like "\r" or "\n".
if (str.indexOf("sun") >= 0){
show(obj01);
}
if (str.indexOf("mon") >= 0){
show(obj02);
}
Answer to the first part:
for (var i=0; i<days.length; i++)
{
str = days[i];
text_txt.text += str + ";" + "\n";
}
I hope I understand you correctly..
I wrote from memory, sorry for typos if there are...
For the second part, add a switch-case
switch(str) {
case "sun":
Show(??);
break;
.
.
.
}

Other ways of counting number of keywords in a complex string

I am reading a file which contains approx 1200 words in the following format:
words:a:/zenb:/fixx:/wew:/sina:/benb:/sixx:/hew:/bin
I need to find how many keywords are there in that text file, by keyword i mean:
zen fix we sin ben six he bin
Right now I am trying to do it with RegExp like this:
var s:String = "words:b:sa:/zenb:/fixx:/wew:/sina:/benb:/sixx:/hew:/bin";
var pattern:RegExp = /:/+/g;
var results:Array = s.match(pattern);
trace(results.length);
Its producing an error, since I am a beginner I really don't understand how this RegExp work , are there any alternate methods to get the same results?
Thanks
Your var pattern:RegExp = /:/+/g; has a syntax error, you skipped a backslash \ change this to :
var pattern:RegExp = /:\/+/g;
and it should work, Alternatively with this format you can use the String split method to get the total word count. Try this:
var s:String = "words:b:sa:/zenb:/fixx:/wew:/sina:/benb:/sixx:/hew:/bin";
var wordCount:Number = s.split(":/").length -1;
trace( wordCount );
Hope that works.
package
{
import flash.display.Sprite;
public class CountWordsExample extends Sprite
{
public function CountWordsExample()
{
super();
// 8 7 0
trace(countWords(
"words:b:sa:/zenb:/fixx:/wew:/sina:/benb:/sixx:/hew:/bin",
":/"),
countWords(
"words:b:sa:/:/fixx:/wew:/sina:/benb:/sixx:/hew:/bin",
":/"),
countWords(
"words:b:sa::zenb::fixx::wew::sina::benb::sixx::hew::bin",
":/"));
}
public static function countWords(words:String, delimiter:String,
countBlanks:Boolean = false):uint
{
var result:uint;
var wordPointer:int = -1;
var delimiterPointer:int;
var delimiterLength:uint = delimiter.length;
if (words.length >= delimiterLength)
{
do
{
delimiterPointer = wordPointer;
wordPointer = words.indexOf(
delimiter, wordPointer + delimiterLength);
if (countBlanks ||
// we moved by more characters, then the length of
// delimiter
wordPointer - delimiterLength > delimiterPointer)
result++;
}
while (wordPointer > -1)
}
return result;
}
}
}
Here's an example of how to count words without ever creating additional arrays or sub-strings of the original string. It also verifies that the words counted have at least one character length.

How I find that string contain a character more then 6 time in Flex?

I want to implement an alogorithm/validation. How can I find out if a string contains a specific character more than 6 times in Flex ?
There are 2 ways, I can think of:
Use RegExp and .replace() like this:
var ch:String = "a"; //Character, that must be checked
var text:String = "This is an example to show how many times '"+ch+"' occured.";
//Matches non-`ch` characters
var regexp:RegExp = new RegExp("[^"+ch+"]","g");
//Replacing non-`ch` characters with empty string
var timesOccured:Number = text.replace(regexp,"").length;
trace(text, ": " ,timesOccured );
Use RegExp and .match() like this:
var ch:String = "a"; //Character, that must be checked
var text:String = "This is an example to show how many times '"+ch+"' occured.";
//Matches `ch` characters
var regexp:RegExp = new RegExp(ch,"g");
var matches:Array = text.match(regexp);
var timesOccured:Number = 0;
//`matches` can be 'null', so we are performing additional check
if( matches ){
timesOccured = matches.length;
}
trace(text, ": " ,timesOccured );
Now when you have timesOccured, you could easily do your validation:
if( timesOccured > 6 ){
//Do some stuff
}else{
//Do other stuff
}
Warning: If your ch is a special character for Regular Expression, like a .,+,(,],\,etc..., you need to escape it, before passing it to regexp variable:
ch = ch.replace(new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"), "\\$&");
a simpler alternative to regular expressions can be the following:
var str:String = "This is an example to show how many...";
//find occurrences for character 'a'
trace("Ocurrences:" + str.split('a').length-1);

String replace \n with <br/> not working

Im currently loading some text through XML via my doc class - this text contains \n tags
XML example:
What im looking to do is replace \n in my string with
I've tried a few things:
string = string.split("\n").join('<br/>');
and
string = string.replace("\n","<br/>");
However tracing out string afterwards, or just seeing what myTextField.htmlText = string; displays, I still see the \n tags
Any ideas?
Code illustrated:
// The string which contains the XML loaded content
var string:String;
var myTextField:TextField = new TextField();
myTextField.defaultTextFormat = myFormat;
myTextField.width = 300;
myTextField.border = false;
myTextField.embedFonts = true;
myTextField.multiline = true;
myTextField.wordWrap = true;
myTextField.selectable = false;
myTextField.htmlText = string;
addChild(myTextField);
You want:
string = string.replace(/\n/g, "<br>");
This will replace all newlines with <br>.
I believe you want:
str = str.replace("\\n", "\n");
OR the following applies to all instances:
str = str.split("\\n").join("\n");
Try that
The solution above didnt work for me
string = string.replace(/\n/g, "<br>");
I was able to do the same thing this way
string = string.replace(new RegExp(String.fromCharCode(13), "<br>");
im using flash cs6-as3
hopefully this helps if the other doesnt work for you