How to use forAll method of Doctrine ArrayCollection? - symfony

Can anybody show example of using forAll method of Doctrine\Common\Collections\ArrayCollection?

It's pretty straightforward. The class you linked to implements the forAll method in a following manner:
foreach ($this->_elements as $key => $element) {
if ( ! $p($key, $element)) {
return false;
}
}
So, based on that you should invoke the forAll like:
$collection = ... #some data
$collection->forAll(function($key, $item){
// Your logic here, based on $key and $item
});
Hope this help....
EDIT (the example):
You have an object of entity Student, which has a OneToMany to student's marks.
You want to check if student has passed all the subjects he/she elected
$student = ....
$allPassed = $student->getMarks()->forAll(function($key, $mark){
return $mark->getValue() != 'F';
});
The $allPassed will hold TRUE if all marks were either 'A', 'B', 'C' or 'D'. Even if one of them were F if will be FALSE.

I would like to highlight that forAll method exits as soon as the inner function returns a false.
Following the example of Perovic, take for instance that the $student has 10 marks, where only one is an 'F'.
If the 'F' mark is the 10th element of the array, the function
$mark->getValue()
will be invoked 10 times.
On the other hand, if the 'F' mark is the first element of the array, $mark->getValue() will be invoked only once, since the function immediately returns false, and forAll method stops evaluating.

Related

xquery to check if the value is null then return null as string

I am new to XQuery. Please guide me to solve the issue below I want to return the null value as a string, if the below expression does not give any value.
Currently, the output doesn't show the 'name' field itself. I want to have a name with null. for eg-
if (IsNull(expression),null,expression)
$output.dataAccessResponse[1]/*:row/*:name/text()
You could use the fn:exists() function to test whether or not there is a text() node.
exists($output.dataAccessResponse[1]/:row/:name/text())
You could also use the fn:boolean() function to test the effective boolean value of the node.
boolean($output.dataAccessResponse[1]/:row/:name/text())
If you wanted to test whether or not there was a significant value i.e. something other than whitespace, you can fn:normalize-space() in a predicate, to ensure that only text() nodes that have meaningful text are selected, and then test fn:exists().
exists($output.dataAccessResponse[1]/:row/:name/text()[normalize-space()])
XQuery doesn't have null, so if you are asking what to return to indicate null, then you would want to return an empty sequence () instead of null.
So, you could execute something like this:
let $name := $output.dataAccessResponse[1]/:row/:name/text()
return
if (fn:exists($name))
then $name
else ()
But at that point, it's really the same as just attempting to select the text() with that XPath and it will either return the text() node or an empty sequence:
$output.dataAccessResponse[1]/:row/:name/text()

how to check whether my cts:and-query or cts:or-query contains any element queries

I have a function which will return either cts:and-query() or cts:or-query().
How can I validate whether the query is empty (without any element or collection queries inside it)?
I want to filter queries like below
cts:and-query(cts:or-query((), ()), ())
The most reliable way to validate a whether a query is empty by your definition is to recursively walk the query until a non-empty query element is encountered, or if not, return true.
It's a little easier to do this by first converting the query to XML:
declare function local:is-empty-query(
$q as schema-element(cts:query)*
)
{
if (empty($q)) then true()
else if (every $e in $q satisfies ($e/self::cts:and-query or $e/self::cts:or-query))
then local:is-empty-query($q/*)
else false()
};
local:is-empty-query(document { cts:and-query((cts:or-query((), ()))) }/*)
=> true()
local:is-empty(document { cts:and-query((cts:or-query((cts:word-query('test'), ())))) }/*)
=> false()

XQuery: map to array of sequences

I have the following map:
let $input := map { 'a-key': 'a-value', 'b-key': ['b-value-1', 'b-value-2'] }
(the length of the b-key array can vary, or be absent; a-key can be present or absent)
I need to create the following array:
[ ('a', 'b', 'b'), 'a-value', 'b-value-1', 'b-value-2' ]
The number of bs in the first sequence should correspond to the number of b-values.
I've tried just about every combination of iterating/map:for-each, etc., and the array either ends up with too much nesting or completely flat...
(n.b. the array is to be passed to a function -- not mine!-- using fn:apply, so needs to be in this form)
It seems hard to build an array containing a sequence that is constructed dynamically, I think you first need to construct the sequence into a variable and then use the square bracket array constructor [$seq] to construct the array with the sequence as the single item. Then you can array:join the other values:
let $input := map { 'a-key': 'a-value', 'b-key': ['b-value-1', 'b-value-2'] }
let $seq := ($input?a-key!'a', (1 to array:size($input?b-key))!'b')
return
array:join(([$seq], array {$input?a-key, $input?b-key?* }))
https://xqueryfiddle.liberty-development.net/nbUY4ku/2
If you are comfortable with the functional-programming side of XQuery, you can create the whole output in two nested "loops" (i.e. folds), one over the keys and the other one over those values that are arrays:
(: the input :)
let $input := map { 'a-key': 'a-value', 'b-key': ['b-value-1', 'b-value-2'] }
(: utility function that adds a single key/value pair to the output array :)
let $update-arr :=
function($arr, $k, $v) {
array:append(array:put($arr, 1, ($arr(1), $k)), $v)
}
(: nested folds over keys and values :)
return fold-left(map:keys($input), [()], function($arr, $key) {
let $k := substring-before($key, '-key')
let $val := $input($key)
return typeswitch($val)
case array(*)
return array:fold-left($val, $arr, function($arr2, $v) {
$update-arr($arr2, $k, $v)
})
default
return $update-arr($arr, $k, $val)
})
You can even abbreviate the array(*) case as return array:fold-left($val, $arr, $update-arr(?, $k, ?)) if you want.
The result is [("a", "b", "b"), "a-value", "b-value-1", "b-value-2"] as expected.

how stacks are formed and value from a method return when the method has TWO recursive calls of itself from within itself

I have tried creating stacks for recursive inorder,preorder,postoreder traversal for binary tree and I was doing it pretty well. In other cases like, for example, for a test case my answer should be 'true',say.And, for example,
boolean method(root)
{
// more code
method(root.left());
method(root.right());
}
,somewhere,the call of method(root.left()) returns false and a call of method(root.right()) returns true that should be our answer. But since call of method(root.left() ) completes first and somewhere, in between it's execution, it might have returned false. then how do we get our result true from method(root.right())?? I think it is related to how stacks are formed and values from a method are returned when recursive calls ,in this way, happen.Explain it and correct me if I am wrong.
You need to return values. The method need to make use of the returned values in its logic to stop/continue the search.
You need to have that the base cases return either true of false. Then when doing the first recursive call you need only do the first if the result is true. The second recursive call would be the result of the method if it's needed. Thus you are looking at something like this:
boolean method(root)
{
if( root == null ) { // base case 1
return false;
}
if( root.value == someValue ) { // base case 2, what should be a positive
return true;
}
// default search left first and return true if true
if( method(root.left()) ) {
return true;
}
// default search right and return true if true
if( method(root.right()) ){
return true;
}
// return false since neither recursive calls were true
return false;
}
This is very verbose and can be written like this instead:
boolean method(root)
{
return root != null && ( root.value == someValue ||
method(root.left()) ||
method(root.right()));
}
I find the last more readable but novices might find the more verbose first one to be more clear.
In both the callee resumes operation after the first recursive call (which might have had it's share of calls as well) and continues it's logic and recurses on the right side if needed.
Don't care about the system stack. Care about the base case and test them. Then do the simplest of added complexity to do the default case so that you see the problem becoming smaller in the recursive call(s). It's much better going from simple to more complex than to try figuring this stuff out by starting at a large tree looking at whats happening with a very deep recursive round.

Backtracking recursively with multiple solutions

function BACKTRACKING-SEARCH(csp) returns a solution, or failure
return RECURSIVE- BACKTRACKING({ }, csp)
function RECURSIVE-BACKTRACKING(assignment,csp) returns a solution, or failure
if assignment is complete then
return assignment
var ←SELECT-UNASSIGNED-VARIABLE(VARIABLES[csp],assignment,csp)
for each value in ORDER-DOMAIN-VALUES(var,assignment,csp) do
if value is consistent with assignment according to CONSTRAINTS[csp] then
add {var = value} to assignment
result ← RECURSIVE-BACKTRACKING(assignment, csp)
if result ̸= failure then
return result
remove {var = value} from assignment
return failure
This is a backtracking recursion algorythm pseudocode from AIMA. However, I don't understand if it returns ALL possible solutions or just first one found. In case it is the last option, could you please help me modify it to return a list of possible solutions instead (or at least updating some global list).
EDIT: I implemented this algorithm in Java. However, there is one problem:
if I don't return assignment, but save it in result instead, the recursion stop condition fails (i.e. it doesn't exist anymore). How can I implement another stop-condition? Maybe I should return true in the end?
Here is my code :
/**
* The actual backtracking. Unfortunately, I don't have time to implement LCV or MCV,
* therefore it will be just ordinary variable-by-variable search.
* #param line
* #param onePossibleSituation
* #param result
*/
public static boolean recursiveBacktrack(Line line, ArrayList<Integer> onePossibleSituation, ArrayList<ArrayList<Integer>> result){
if (onePossibleSituation.size() == line.getNumOfVars()){
// instead of return(assignment)
ArrayList<Integer> situationCopy = new ArrayList<Integer>();
situationCopy.addAll(onePossibleSituation);
result.add(situationCopy);
onePossibleSituation.clear();
}
Block variableToAssign = null;
// iterate through all variables and choose one unassigned
for(int i = 0; i < line.getNumOfVars(); i++){
if(!line.getCspMiniTaskVariables().get(i).isAssigned()){
variableToAssign = line.getCspMiniTaskVariables().get(i);
break;
}
}
// for each domain value for given block
for (int i = line.getCspMiniTaskDomains().get(variableToAssign.getID())[0];
i <= line.getCspMiniTaskDomains().get(variableToAssign.getID())[0]; i++){
if(!areThereConflicts(line, onePossibleSituation)){
//complete the assignment
variableToAssign.setStartPositionTemporary(i);
variableToAssign.setAssigned(true);
onePossibleSituation.add(i);
//do backtracking
boolean isPossibleToPlaceIt = recursiveBacktrack(line,onePossibleSituation,result);
if(!isPossibleToPlaceIt){
return(false);
}
}
// unassign
variableToAssign.setStartPositionTemporary(-1);
variableToAssign.setAssigned(false);
onePossibleSituation.remove(i);
}
// end of backtracking
return(false);
}
This code checks if solution found and if it is, returns the solution. Otherwise, continue backtracking. That means, it returns the first solution found.
if result ̸= failure then
return result
remove {var = value} from assignment
You can modify it like that:
if result ̸= failure then
PRINT result // do not return, just save the result
remove {var = value} from assignment
Or, better, modify this part:
if assignment is complete then
print assignment
return assignment // print it and return
About edited question:
First, return true in the first if, so recursion will know that it found a solution. The second step, there is a mistake, probably:
if(!isPossibleToPlaceIt){
return(false);
}
Should be
if(isPossibleToPlaceIt){
return(true);
}
Because if your backtracking has found something, it returns true, which means you don't have to check anything else any longer.
EDIT#2: If you want to continue backtracking to find ALL solutions, just remove the whole previous if section with return:
//if(isPossibleToPlaceIt){
// return(true);
//}
So we will continue the search in any way.

Resources