AS3 Custom string formula parser - actionscript-3

My goal is to create some kind of Parser to parse string formulas, similar to Excel formulas.
Formula string example (barcode example) -
"CONCAT('98', ZEROFILL([productNumber],5,'0'), ZEROFILL(EQUATION([weightKG]*1000),5,'0'))"
where
'98' - String
[productNumber] and [weightKG] - are variables that can be changed
CONCAT, ZEROFILL and EQUATION are methods which exist in class
For this formula with variables [productNumber] = '1' and [weightKG] = 0.1 result must be
'980000100100'
The question is how to split/parse whole string to parts and detect methods, variables and string values?
Another idea occurred, while i was typing - is to store whole formula in XML format.
Thank You.

You can use String.split() to get an array of substrings.
However, using your example, calling split(",") would give you the following array:
[0]=CONCAT('98'
[1]= ZEROFILL([productNumber]
[2]=5
[3]='0')
[4]= ZEROFILL(EQUATION([weightKG]*1000)
[5]=5
[6]='0'))
That doesn't seem like it will be very helpful for your project. Instead, you might think about creating a parse() function with some logic to find useful substrings:
function parse(input:String):Array {
var firstParen:int = input.indexOf("(");
var lastParen:int = input.lastIndexOf(")");
var formulaName:String = input.substring(0, firstParen);
var arguments:String = input.substring(firstParen, lastParen);
var argumentList:Array = parseArgs(arguments);
var result:Array = new Array();
result.push(formulaName);
//Recursively call parse() on the argumentList
foreach (var elem:* in argumentList) {
result.push(elem); //Could be string or array.
}
}
function parseArgs(input:String):Array {
// Look for commas that aren't enclosed inside parenthesis and
// construct an array of substrings based on that.
//A regex may be helpful here, but the implementation is left
//as an exercise for the reader.
}

Related

store string into array

In MySQL, I have a field name postcodes and the type is LONGTEXT. It stores several postcodes being separated by comma. How would I retrieve that and store it as an array for other use ?
you can use the PHP method explode().
one think you can't do, is to do a where x = x on it in the database.
In the model, you can set the mutator methods:
public function getPostcodesAttribute($value) {
return explode(',',$value);
}
public function setPostcodesAttribute($value) {
$this->attributes['postcodes'] = implode(',',$value);
}
Lets say that you have the result stored in a string like this:
$s = "6000,5447"; //$s = $array->postcodes;
you can get the each value on an index in an array using this:
$values= explode(",", $s);
echo $values[0]; // 6000
Or even better.. you can store it as json, and retrieve it as json in array format.
Store it as a JSON field in MySQL, Laravel encode and decode them when you retrieve and save them respectively
in your migration
$table->json('field_name');
then in the model
protected $json = ['field_name'];
then whenever you access the field, laravel will convert it to an array for you, you don't have to call any explicit methods.
Doc - https://laravel.com/docs/5.7/eloquent-mutators#attribute-casting
// the final array all the post codes are collected.
$postCodes = [];
foreach (Model::pluck('postcodes') as $stringCodes)
foreach (explode(',', $stringCodes) as $postCode) $postCodes[] = $postCode;

SSIS: How can I convert an NTEXT input to a string to perform a Split function in a script component?

I receive a Unicode text flat-file in which one column is a single fixed-length value, and the other contains a list values delimited by a vertical pipe '|'. The length of the second column and the number of delimited values it contains will vary greatly. In some cases the column will be up to 50000 characters wide, and could contain a thousand or more delimited values.
Input file Example:
[ObjectGUID]; [member]
{BD3481AF8-2CDG-42E2-BA93-73952AFB41F3}; CN=rGlynn SrechrshiresonIII,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp
{AC365A4F8-2CDG-42E2-BA33-73933AFB41F3}; CN=reeghler Johnson,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp|CN=rCoefler Cellins,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp|CN=rDasije M. Delmogeroo,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp|CN=rCurry T. Carrollton,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp|CN=yMica Macintosh,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp
My idea is to perform a Split operation on this column and create a new row for each value. I am attempting to use a script component to perform the split.
The width of the delimited column can easily exceed the 4000 character limit of DT-WSTR, so I chose NTEXT as the datatype. This presents problem because the .Split method I am familar with requires a string. I am attempting to convert the NTEXT to a string in the script component.
Here is my code:
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
var stringMember = Row.member.ToString();
var groupMembers = stringMember.Split('|');
foreach (var groupMember in groupMembers)
{
this.Output0Buffer.AddRow();
this.Output0Buffer.objectGUID = Row.objectGUID;
this.Output0Buffer.member = groupMember;
}
}
The output I am trying to get would be this:
[ObjectGUID] [member]
{BD3481AF8-2CDG-42E2-BA93-73952AFB41F3} CN=rGlynn SrechrshiresonIII,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp
{AC365A4F8-2CDG-42E2-BA33-73933AFB41F3} CN=reeghler Johnson,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp
{AC365A4F8-2CDG-42E2-BA33-73933AFB41F3} CN=rCoefler Cellins,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp
{AC365A4F8-2CDG-42E2-BA33-73933AFB41F3} CN=rDasije M. Delmogeroo,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp
{AC365A4F8-2CDG-42E2-BA33-73933AFB41F3} CN=rCurry T. Carrollton,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp
{AC365A4F8-2CDG-42E2-BA33-73933AFB41F3} CN=yMica Macintosh,OU=Users,OU=PRV,OU=LOL,DC=ent,DC=keke,DC=cqb,DC=corp
But what I am in fact getting is this:
[ObjectGUID] [member]
{BD3481AF8-2CDG-42E2-BA93-73952AFB41F3} Microsoft.SqlServer.Dts.Pipeline.BlobColumn
{AC365A4F8-2CDG-42E2-BA33-73933AFB41F3} Microsoft.SqlServer.Dts.Pipeline.BlobColumn
What might I be doing wrong?
The following code worked:
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
var blobLength = Convert.ToInt32(Row.member.Length);
var blobData = Row.member.GetBlobData(0, blobLength);
var stringData = System.Text.Encoding.Unicode.GetString(Row.member.GetBlobData(0, Convert.ToInt32(Row.member.Length)));
var groupMembers = stringData.Split('|');
foreach (var groupMember in groupMembers)
{
this.Output0Buffer.AddRow();
this.Output0Buffer.CN = Row.CN;
this.Output0Buffer.ObjectGUID = Row.ObjectGUID;
this.Output0Buffer.member = groupMember;
}
}
I was trying to perform an implicit conversion as I would in PowerShell, but was actually just passing some object metadata to the string output. This method properly splits my members and builds a complete row.

MATLAB: Is there a method to better organize functions for experiments?

I will run a set of experiments. The main method evaluated has the following signature:
[Model threshold] = detect(...
TrainNeg, TrainPos, nf, nT, factors, ...
removeEachStage, applyEstEachStage, removeFeatures);
where removeEachStage, applyEstEachStage, and removeFeatures are booleans. You can see that if I reverse the order of any of these boolean parameters I may get wrong results.
Is there a method in MATLAB that allows better organization in order to minimize this kind of error? Or is there any tool I can use to protect me against these errors?
Organization with a struct
You could input a struct that has these parameters as it's fields.
For example a structure with fields
setts.TrainNeg
.TrainPos
.nf
.nT
.factors
.removeEachStage
.applyEstEachStage
.removeFeatures
That way when you set the fields it is clear what the field is, unlike a function call where you have to remember the order of the parameters.
Then your function call becomes
[Model threshold] = detect(setts);
and your function definition would be something like
function [model, threshold] = detect(setts)
Then simply replace the occurrences of e.g. param with setts.param.
Mixed approach
You can also mix this approach with your current one if you prefer, e.g.
[Model threshold] = detect(in1, in2, setts);
if you wanted to still explicitly include in1 and in2, and bundle the rest into setts.
OOP approach
Another option is to turn detect into a class. The benefit to this is that a detect object would then have member variables with fixed names, as opposed to structs where if you make a typo when setting a field you just create a new field with the misspelled name.
For example
classdef detect()
properties
TrainNeg = [];
TrainPos = [];
nf = [];
nT = [];
factors = [];
removeEachStage = [];
applyEstEachStage = [];
removeFeatures =[];
end
methods
function run(self)
% Put the old detect code in here, use e.g. self.TrainNeg to access member variables (aka properties)
end
end

LINQ variable to list of string without using column names?

In an C# ASP.Net MVC project, I'm trying to make a List<string> from a LINQ variable.
Now this might be a pretty basic thing, but I just cannot get that to work without using the actual column names for the data in that variable. The thing is that in the interests of trying to make the program as dynamic as possible, I'm leaving it up to a stored procedure to get the data out. There can be any amount of any which way named columns depending on where the data is fetched from. All I care about is taking all of their values into a List<string>, so that I can compare user-input values with them in program.
Pointing to the columns by their names in the code means I'd have to make dozens of overloaded methods that all just basically do the same thing. Below is false non-functioning code. But it should open up the idea of what I mean.
// call for stored procedure
var courses = db.spFetchCourseInformation().ToList();
// if the data fails a check on a single row, it will not pass the check
bool passed = true;
foreach (var i in courses)
{
// each row should be cast into a list of string, which can then be validated
// on a row-by-row basis
List courseRow = new List();
courseRow = courses[i]; // yes, obviously this is wrong syntax
int matches = 0;
foreach (string k in courseRow)
{
if (validator.checkMatch(courseRow[k].ToString()))
{
matches++;
}
}
if (matches == 0)
{
passed = false;
break;
}
}
Now below is an example of how I currently have to do it because I need to use the names for the columns
for (int i = 0; i < courses.Count; i++)
{
int matches = 0;
if (validator.checkMatch(courses[i].Name))
matches++;
if (validator.checkMatch(courses[i].RandomOtherColumn))
matches++;
if (validator.checkMatch(courses[i].RandomThirdColumn))
matches++;
if (validator.checkMatch(courses[i].RandomFourthColumn))
matches++;
/* etc...
* etc...
* you get the point
* and one of these for each and every possible variation from the stored procedure, NOT good practice
* */
Thanks for help!
I'm not 100% sure what problem you are trying to solve (matching user data to a particular record in the DB?), but I'm pretty sure you're going about this in slightly the wrong fashion by putting the data in a List. I
t should be possible to get your user input in an IDictionary with the key being used for the column name, and the object as the input data field.
Then when you get the data from the SP, you can get the data back in a DataReader (a la http://msmvps.com/blogs/deborahk/archive/2009/07/09/dal-access-a-datareader-using-a-stored-procedure.aspx).
DataReaders are indexed on column name, so if you run through the keys in the input data IDictionary, you can check the DataReader to see if it has matching data.
using (SqlDataReader reader = Dac.ExecuteDataReader("CustomerRetrieveAll", null))
{
while (reader.Read())
{
foreach(var key in userInputDictionary.AllKeys)
{
var data = reader[key];
if (data != userInputDictionary[key]) continue;
}
}
}
Still not sure about the problem you are solving but, I hope this helps!
A little creative reflection should do the trick.
var courses = db.spFetchCourseInformation()
var values = courses.SelectMany(c => c.GetType().GetProperties() // gets the properties for your object
.Select(property => property.GetValue(c, null))); // gets the value of each property
List<string> stringValues = new List<string>(
values.Select(v => v == null ? string.Empty : v.ToString()) // some of those values will likely be null
.Distinct()); // remove duplicates

ActionScript: Is there ever a good reason to use 'as' casting?

From what I understand of ActionScript, there are two kinds of casts:
var bar0:Bar = someObj as Bar; // "as" casting
var bar1:Bar = Bar(someObj); // "class name" casting (for want of a better name)
Also, and please correct me if I'm wrong here, as casting will either return an instance of the class or null, while "class name" casting will either return an instance of the class or raise an exception if the cast is impossible – other than this, they are identical.
Given this, though, as casting seems to be a massive violation of the fail-fast-fail-early principle... And I'm having trouble imagining a situation where it would be preferable to use an as cast rather than a class name cast (with, possibly, an instanceof thrown in there).
So, my question is: under what circumstances would it be preferable to use as casting?
There are a couple of points in this discussion worth noting.
There is a major difference in how the two work, Class() will attempt to cast the object to the specified Class, but on failure to do so will (sometimes, depends on datatype) throw a runtime error. On the other hand using object as Class will preform a type check first, and if the specified object cannot be cast to the indicated Class a null value is returned instead.
This is a very important difference, and is a useful tool in development. It allows us to do the following:
var o:MyClass = myArray[i] as MyClass;
if(o)
{
//do stuff
}
I think the usefulness of that is pretty obvious.
"as" is also more consistent with the rest of the language (ie: "myObject is MyClass").
The MyClass() method has additional benefits when working with simple data types (int, Number, uint, string) Some examples of this are:
var s:String = "89567";
var s2:String = "89 cat";
var n:Number = 1.9897;
var i:int = int(s); // i is = 89567, cast works
var i2:int = int(s2); //Can't convert so i2 is set to 0
var i3:int = int(n); // i = 1
var n2:Number = Number(s2); // fails, n2 = NaN
//when used in equations you'll get very different results
var result:int = int(n) * 10; //result is 10
var result:int = n * 10; //result is 19.89700
var result:int = int(s2) * 10; //result is 0
trace(s2 as Number); //outputs null
trace(s2 as int); //outputs null
trace(Number(s2)); //outputs NaN
This is a good and important topic, as a general rule I use "as" when working with Objects and Cast() when using simpler data types, but that's just how I like to structure my code.
You need to use as to cast in two scenarios: casting to a Date, and casting to an Array.
For dates, a call to Date(xxx) behaves the same as new Date().toString().
For arrays, a call to Array(xxx) will create an Array with one element: xxx.
The Class() casting method has been shown to be faster than as casting, so it may be preferable to as when efficiency matters (and when not working with Dates and Arrays).
import flash.utils.*;
var d = Date( 1 );
trace( "'" + d, "'is type of: ",getQualifiedClassName( d ) );
var a:Array = Array( d );
trace( "'" + a, "' is type of: ", getQualifiedClassName( a ) );
//OUTPUT
//'Mon Jun 15 12:12:14 GMT-0400 2009 'is type of: String
//'Mon Jun 15 12:12:14 GMT-0400 2009 ' is type of: Array
//COMPILER ERRORS/WARNINGS:
//Warning: 3575: Date(x) behaves the same as new Date().toString().
//To cast a value to type Date use "x as Date" instead of Date(x).
//Warning: 1112: Array(x) behaves the same as new Array(x).
//To cast a value to type Array use the expression x as Array instead of Array(x).
`
They actually do different things...when you say
myvar as ClassName
You are really just letting the compiler know that this object is either a ClassName or a subclass of ClassName
when you say:
ClassName(myvar)
It actually tries to convert it to that type of object.
so if your object is a or a descent of the class and you do not need to convert it you would use as
examples:
var myvar:String = '<data/>';
var othervar:XML = XML(myvar); //right
var myvar:String = '<data/>';
var othervar:XML = (myvar as XML); //wrong
var myvar:XML = <data/>;
var othervar:XML = myvar as XML; // right
Use 'as' with arrays.
var badArray:Array;
badArray = Array(obj);
Will yield an array of length one with the original array in the first element. If you use 'as' as follows, you get the exptected result.
var goodArray:Array;
goodArray = obj as Array;
Generally, 'as' is preferable to 'Class()' in ActionScript as it behaves more like casting in other languages.
I use it when I have an ArrayCollection of objects and need to enumerate through them, or use a selector function.
e.g.
var abc:mytype = mycollection.getItemAt(i) as mytype