Modify formula stored in string via VBA - regex

(I have hundreds of rows need to change. The data is like this
activity_id equation
5225518 D0312_ABC * (S3765+S3790+S3762+S3763+S3770+S3764+S4480) * (1-(S2820+S0560))*(1-S1965)*(1-C0151)
7306234 D0300_BCD * C0502 * (1-(S0191))*(1-S1965)
8293425 D0798_CDE * P0692 * (1-(S0191+S2820+S0560+S0290+S0960))*(1-S1965)
9119429 D0793_DEF * S2605 * (1-S0290)*(1-S1965)
I need to combine the two "1-something" together and there is a pattern.
When ever there is a (1-(Sxxx+Sxxxx))*(1-(Sxxx+Sxxxx)),
combine them into one which is (1-(Sxxx+Sxxxx +Sxxx+Sxxxx))
So I only need to change everything with Sxxxx, you can ignore Cxxxx, Dxxxx, Pxxxx, ...
SO I need to change it to:
activity_id equation
5225518 D0312_ABC * (S3765+S3790+S3762+S3763+S3770+S3764+S4480) * (1-(S2820+S0560+S1965))*(1-C0151)
7306234 D0300_BCD * C0502 * (1-(S0191+S1965))
8293425 D0798_CDE * P0692 * (1-(S0191+S2820+S0560+S0290+S0960+S1965))
9119429 D0793_DEF * S2605 * (1-(S0290+S1965))

The following regexp certainly may and arguably should be improved.
Option Explicit
Private m_Rex As RegExp
Private Const SEARCH_PATTERN As String = "\(1-\(?((S\d{4}\+?)+)\)?\)\*\(1-\(?((S\d{4}\+?)+)\)?\)"
' $0 $2
Private Const REPLACE_PATTERN As String = "(1-($1+$3))"
Public Function Simplify(ByVal AVeryParticularFormula As String) As String
If m_Rex Is Nothing Then
Set m_Rex = New RegExp
m_Rex.Global = False
m_Rex.MultiLine = False
m_Rex.IgnoreCase = False
m_Rex.Pattern = SEARCH_PATTERN
End If
Do
Simplify = m_Rex.Replace(AVeryParticularFormula, REPLACE_PATTERN)
If Simplify = AVeryParticularFormula Then Exit Do
AVeryParticularFormula = Simplify
Loop
End Function
? Simplify("D0312_ABC * (S3765+S3790+S3762+S3763+S3770+S3764+S4480) * (1-(S2820+S0560))*(1-S1965)*(1-C0151)")
D0312_ABC * (S3765+S3790+S3762+S3763+S3770+S3764+S4480) * (1-(S2820+S0560+S1965))*(1-C0151)
? Simplify("D0300_BCD * C0502 * (1-(S0191))*(1-S1965)")
D0300_BCD * C0502 * (1-(S0191+S1965))
? Simplify("D0798_CDE * P0692 * (1-(S0191+S2820+S0560+S0290+S0960))*(1-S1965)")
D0798_CDE * P0692 * (1-(S0191+S2820+S0560+S0290+S0960+S1965))
? Simplify("D0793_DEF * S2605 * (1-S0290)*(1-S1965)")
D0793_DEF * S2605 * (1-(S0290+S1965))

Related

How to create a Hashtbl with a custom type as key?

I'm trying to create a Hashtbl with a node type I've written.
type position = float * float
type node = position * float
I'd like to create a Hashtbl with nodes as keys pointing to a float, and have something like this :
[((node), float))]
This is what I've tried so far :
module HashtblNodes =
struct
type t = node
let equal = ( = )
let hash = Hashtbl.hash
end;;
Along with :
module HashNodes = Hashtbl.Make(HashtblNodes);;
I'm not sure it's the right implementation to do what I explained before, plus I don't know how I could create the table with this.
How would I be able to do this please?
Your approach just works (though see a comment to your question about "you don't actually need to use the functor").
Starting from your definitions in the question:
# let tbl = HashNodes.create 1 ;;
val tbl : '_weak2 HashNodes.t = <abstr>
# let node1 = ((1.0, 2.0), 3.0);;
val node1 : (float * float) * float = ((1., 2.), 3.)
# let node2 = ((-1.0, -2.0), -3.0);;
val node2 : (float * float) * float = ((-1., -2.), -3.)
# HashNodes.add tbl node1 100.0;;
- : unit = ()
# HashNodes.add tbl node2 200.0;;
- : unit = ()
# HashNodes.find tbl ((1.0, 2.0), 3.0) ;;
- : float = 100.
#

Doctrine 2 left join with in a tree

I have two entities: People and Document
A people can have n childrens:
/**
*
* #ORM\ManyToOne(targetEntity="People")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="dad_id", referencedColumnName="id")
* })
*/
private $dad;
/**
*
* #ORM\OneToMany(targetEntity="People", mappedBy="dad")
*/
private $childrens;
And a people can have n Documents:
DocumentEntity:
/**
*
* #ORM\ManyToOne(targetEntity="People")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="people_id", referencedColumnName="id")
* })
*/
private $people;
I want to get all peoples (and their children) and their documents of type License in one query:
$qb = $this->em->getRepository('People')->createQueryBuilder('p');
$qb
->select(array('p','d'))
->leftJoin('p.documents','d','WITH','d.type = :type')
->setParameter('type','license')
;
$peoples = $qb->getQuery()->getResult();
Fine, if i call $people->getDocuments() returns only Documents of type 'License'. But when i do this '$people->getChildrens()[0]->getDocuments()' returns for me all Documents of this people.
How i can do a 'left join WITH' cascading on a tree structure?

How to do Doctrine2 calculated fields ordering

I've got the following doctrine2 query working nicely, it retrieves all 'markers' within some geographical radius.
$qb->select('marker')
->from('SndSpecialistLocator\Entity\Marker', 'marker')
->where('DISTANCE(marker.location, POINT_STR(:point)) < :distance')
->setParameter('point', $point)
->setParameter('distance', $radius);
Now I want to sort them by distance.
$qb->select('marker (DISTANCE(marker.location, POINT_STR(:point))) AS distance')
->from('SndSpecialistLocator\Entity\Marker', 'marker')
->where('DISTANCE(marker.location, POINT_STR(:point)) < :distance')
->setParameter('point', $point)
->orderBy('distance', 'DESC')
->setParameter('distance', $radius);
But unfortunately this does not work, I am wondering is this possible as distance is not a real property of my entity, but a calculated one?
What is the trick here?
Alternatively, try using HIDDEN in your call to select() :
$qb->select('m as marker, (DISTANCE(m.location, POINT_STR(:point))) as HIDDEN distance')
// note HIDDEN added here --->------->------->------->------->------->---^
->from('SndSpecialistLocator\Entity\Marker', 'm')
->where('DISTANCE(m.location, POINT_STR(:point)) < :distance')
->setParameter('point', $point)
->orderBy('distance', 'ASC')
->setParameter('distance', $radius)
->setMaxResults(5);
$query = $qb->getQuery();
$result = $query->execute();
Adding HIDDEN to the SELECT clause hides it from the results but allows it to be used in the orderby clause. Your $result should then contain the objects you want without having to do the extra array_walk.
Unfortunately, ordering by aliases is not possible.
What you can do* instead is to manually repeat the function in your orderBy statement:
$qb->select('marker (DISTANCE(marker.location, POINT_STR(:point))) AS distance')
->from('SndSpecialistLocator\Entity\Marker', 'marker')
->where('DISTANCE(marker.location, POINT_STR(:point)) < :distance')
->setParameter('point', $point)
->orderBy('DISTANCE(marker.location, POINT_STR(:point))', 'DESC')
->setParameter('distance', $radius);
*We will probably all end up in dev-hell for stepping off the holy path of DRY
Found the solution.
$qb->select('m as marker, (DISTANCE(m.location, POINT_STR(:point))) as distance')
->from('SndSpecialistLocator\Entity\Marker', 'm')
->where('DISTANCE(m.location, POINT_STR(:point)) < :distance')
->setParameter('point', $point)
->orderBy('distance', 'ASC')
->setParameter('distance', $radius)
->setMaxResults(5);
$query = $qb->getQuery();
$result = $query->execute();
/**
* Convert the resulting associative array into one containing only the entity objects
*
* array (size=5)
* 0 =>
* array (size=2)
* 'marker' =>
* object(SndSpecialistLocator\Entity\Marker)[647]
* protected 'id' => int 43
* protected 'title' => string 'c5d07acdd47efbe38a6d0bf4ec64f333' (length=32)
* private 'location' =>
* object(SndSpecialistLocator\Orm\Point)[636]
* private 'lat' => float 52.2897
* private 'lng' => float 4.84268
* 'distance' => string '0.0760756823433058' (length=18)
* 1 => ...
*
* array (size=5)
* 0 =>
* object(SndSpecialistLocator\Entity\Marker)[647]
* protected 'id' => int 43
* protected 'title' => string 'c5d07acdd47efbe38a6d0bf4ec64f333' (length=32)
* private 'location' =>
* object(SndSpecialistLocator\Orm\Point)[636]
* private 'lat' => float 52.2897
* private 'lng' => float 4.84268
* 1 => ...
*
*/
array_walk($result, function (&$item, $key)
{
$item = $item['marker'];
});

how to remove string from URL? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to strip out a url variable
I have url http://localhost/abc/detail.cfm?iId=1711471&countrysearch=3693&itemnumbersearch=&keywordsearch=&purl=%2FIGPCI%2Fthumbs%2Ecfm%3Fcountrysearch%3D3693%26itemnumbersearch%3D%26keywordsearch%3D%26x%3D78%26y%3D10&productid=1111&recordindex=1.
I want to search product details on clicking link called "next" each time i need to prepare new URL with new value of productid and recordindex.for example i have four product with respect to countryid="3693",
productid productname
1 p1
2 p2
3 p3
4 p4
when next click new URL prepare with productid=1 and recordindex=1,again click then URL is productid=2 and record id =2 and so on.
for getting URL i have used following code:
<cfset currentURL = "#CGI.SERVER_NAME#" & "#CGI.PATH_INFO#" & "#CGI.query_string#">
which give me the current url
then i prepare new url with below code:
<cfif queryString.recordset gt 0> <cfset recordindex=#recordindex#+1> <cfset newUrl=currentURL & '&productid=#queryString.poductid[recordindex]#&recordindex=#recordindex#' </cfif>
with this code that each time it's append url value with old with new one.
like:
http://localhost/abc/detail.cfm?iId=1711471&countrysearch=3693&itemnumbersearch=&keywordsearch=&purl=%2FIGPCI%2Fthumbs%2Ecfm%3Fcountrysearch%3D3693%26itemnumbersearch%3D%26keywordsearch%3D%26x%3D78%26y%3D10&productid=1111&recordindex=1&productid=2&recordindex=2
my question how to remove old &productid=1111&recordindex=1 in old URL.i tried with replace function but it replace when string are match,in my case every time product and recordindex values are change.how to remove old string using regular expression.please help me.
Thanks
You don't need regex for this. In fact, someone has already built a UDF for this.
QueryStringDeleteVar
Example:
<cfset currentURL = CGI.SERVER_NAME & CGI.PATH_INFO & queryStringDeleteVar("productid,recordindex")>
UDF code:
<cfscript>
/**
* Deletes a var from a query string.
* Idea for multiple args from Michael Stephenson (michael.stephenson#adtran.com)
*
* #param variable A variable, or a list of variables, to delete from the query string.
* #param qs Query string to modify. Defaults to CGI.QUERY_STRING.
* #return Returns a string.
* #author Nathan Dintenfass (michael.stephenson#adtran.comnathan#changemedia.com)
* #version 1.1, February 24, 2002
*/
function queryStringDeleteVar(variable){
//var to hold the final string
var string = "";
//vars for use in the loop, so we don't have to evaluate lists and arrays more than once
var ii = 1;
var thisVar = "";
var thisIndex = "";
var array = "";
//if there is a second argument, use that as the query string, otherwise default to cgi.query_string
var qs = cgi.query_string;
if(arrayLen(arguments) GT 1)
qs = arguments[2];
//put the query string into an array for easier looping
array = listToArray(qs,"&");
//now, loop over the array and rebuild the string
for(ii = 1; ii lte arrayLen(array); ii = ii + 1){
thisIndex = array[ii];
thisVar = listFirst(thisIndex,"=");
//if this is the var, edit it to the value, otherwise, just append
if(not listFind(variable,thisVar))
string = listAppend(string,thisIndex,"&");
}
//return the string
return string;
}
</cfscript>
Although, since you're looking to replace URL parameter values, QueryStringChangeVar would probably be more of what you want.
<cfscript>
/**
* Changes a var in a query string.
*
* #param name The name of the name/value pair you want to modify. (Required)
* #param value The new value for the name/value pair you want to modify. (Required)
* #param qs Query string to modify. Defaults to CGI.QUERY_STRING. (Optional)
* #return Returns a string.
* #author Nathan Dintenfass (nathan#changemedia.com)
* #version 2, September 5, 2002
*/
function QueryStringChangeVar(variable,value){
//var to hold the final string
var string = "";
//vars for use in the loop, so we don't have to evaluate lists and arrays more than once
var ii = 1;
var thisVar = "";
var thisIndex = "";
var array = "";
var changedIt = 0;
//if there is a third argument, use that as the query string, otherwise default to cgi.query_string
var qs = cgi.query_string;
if(arrayLen(arguments) GT 2)
qs = arguments[3];
//put the query string into an array for easier looping
array = listToArray(qs,"&");
//now, loop over the array and rebuild the string
for(ii = 1; ii lte arrayLen(array); ii = ii + 1){
thisIndex = array[ii];
thisVar = listFirst(thisIndex,"=");
//if this is the var, edit it to the value, otherwise, just append
if(thisVar is variable){
string = listAppend(string,thisVar & "=" & value,"&");
changedIt = 1;
}
else{
string = listAppend(string,thisIndex,"&");
}
}
//if it was not changed, add it!
if(NOT changedIt)
string = listAppend(string,variable & "=" & value,"&");
//return the string
return string;
}
</cfscript>

Can't use same parameter twice in custom function

I wrote a custom DQL function. In this function I use the same parameter twice:
public function getSql(SqlWalker $sqlWalker)
{
$point1_lat = $this->point1_lat->dispatch($sqlWalker);
$point1_lon = $this->point1_lon->dispatch($sqlWalker);
$point2_lat = $this->point2_lat->dispatch($sqlWalker);
$point2_lon = $this->point2_lon->dispatch($sqlWalker);
$unitFactor = 6366.56486; // earth radius in km
return "
$unitFactor *
2 *
ASIN(
SQRT(
POWER(
SIN(($point1_lat - $point2_lat) * pi()/180/2),
2
) +
COS($point1_lat * pi()/180) *
COS($point2_lat * pi()/180) *
POWER(
SIN(($point1_lon - $point2_lon) * pi()/180/2),
2
)
)
)
";
}
This is how the query is executed:
$q = \App::get()->getEntityManager()->createQuery('
SELECT
s,
GEO_DISTANCE(
:lat,
:lng,
s.glat,
s.glng
) AS distance
FROM
\Application\Geo\Entity\Street s
');
$q->setMaxResults(10);
$q->setParameters(array(
'lat' => 52.25948,
'lng' => 6.76403,
));
$result = $q->getResult();
This however gives me the following exception:
Message: SQLSTATE[HY093]: Invalid parameter number: number of bound
variables does not match number of tokens
The following SQL is returned by getSql():
6366.56486 *
2 *
ASIN(
SQRT(
POWER(
SIN((? - g0_.glat) * pi()/180/2),
2
) +
COS(? * pi()/180) *
COS(g0_.glat * pi()/180) *
POWER(
SIN((? - g0_.glng) * pi()/180/2),
2
)
)
)
So I guess the exception is thrown because the named parameters are returned as indexed parameters. Is this a bug in doctrine or am I doing something wrong?
This is not a bug, you can only use each parameter once, as the dispatch() function puts the value on the stack once, to match one ? placeholder in the query.
As a workaround, you can call dispatch() several times:
public function getSql(SqlWalker $sqlWalker)
{
$point1_lat_a = $this->point1_lat->dispatch($sqlWalker);
$point1_lat_b = $this->point1_lat->dispatch($sqlWalker);
$point1_lon = $this->point1_lon->dispatch($sqlWalker);
$point2_lat_a = $this->point2_lat->dispatch($sqlWalker);
$point2_lat_b = $this->point2_lat->dispatch($sqlWalker);
$point2_lon = $this->point2_lon->dispatch($sqlWalker);
$unitFactor = 6366.56486; // earth radius in km
return "
$unitFactor *
2 *
ASIN(
SQRT(
POWER(
SIN(($point1_lat_a - $point2_lat_a) * pi()/180/2),
2
) +
COS($point1_lat_b * pi()/180) *
COS($point2_lat_b * pi()/180) *
POWER(
SIN(($point1_lon - $point2_lon) * pi()/180/2),
2
)
)
)
";
}