Evaluating MongoDB-like JSON Queries in PHP - php

Consider the following (rather complicated) query expressed in this JSON object:
{
"name": "Kindle Fire",
"sale": true,
"price": {
"$gt": 199,
"$lt": 264
},
"price.vat": { // bogus, just to show $a['price.vat'] == $a['price']['vat']
"$lte": 1.2
},
"$or": {
"qty": {
"$gt": 30
},
"eta": {
"$or": {
"$lt": 3,
"$gt": 30
}
}
},
"countriesAvailable": {
"$in": [
"US",
"CA"
]
}
}
Objective
I want to parse that JSON so that it evaluates to the PHP equivalent of (where $a is my target data):
$a['name'] == 'Kindle Fire' &&
$a['sale'] == true &&
(
$a['price'] > 199 && $a['price'] < 264
) &&
$a['price']['vat'] <= 1.2 &&
(
$a['qty'] > 30 ||
(
$a['eta'] < 3 || $a['eta'] > 30
)
) &&
in_array($a['countriesAvailable'], array('US', 'CA'))
I have little experience building expression evaluators. My idea is to traverse the query from the innermost level to the outermost level, calling the corresponding MongoDB operator methods as needed.
Assuming $a matches the query, this would be the evaluation plan:
$query = array();
$query['name'] = true;
$query['sale'] = true;
$query['price'] = array();
$query['price']['$gt'] = true;
$query['price']['$lt'] = true;
$query['price']['vat'] = array();
$query['price']['vat']['$lte'] = true;
$query['$or'] = array();
$query['$or']['qty'] = array();
$query['$or']['qty']['$gt'] = false;
$query['$or']['eta'] = array();
$query['$or']['eta']['$or'] = array();
$query['$or']['eta']['$or']['$lt'] = true;
$query['$or']['eta']['$or']['$gt'] = false;
$query['countriesAvailable'] = array();
$query['countriesAvailable']['$in'] = true;
The second step:
$query = array();
$query['name'] = true;
$query['sale'] = true;
$query['price'] = array();
$query['price']['$gt'] = true;
$query['price']['$lt'] = true;
$query['price']['vat'] = true;
$query['$or'] = array();
$query['$or']['qty'] false;
$query['$or']['eta'] = array();
$query['$or']['eta']['$or'] true;
$query['countriesAvailable'] = true;
The third step:
$query = array();
$query['name'] = true;
$query['sale'] = true;
$query['price'] = true;
$query['$or'] = array();
$query['$or']['qty'] false;
$query['$or']['eta'] true;
$query['countriesAvailable'] = true;
The fourth step:
$query = array();
$query['name'] = true;
$query['sale'] = true;
$query['price'] = true;
$query['$or'] = true;
$query['countriesAvailable'] = true;
Since all the values are booleans the evaluation ends returning !in_array(false, $query, true).
If a better approach exists, let me know.
Problem: Accessing Parent Array Keys
I'm stuck trying to get the innermost the elements and the relevant (ignoring operators) array index path, for instance, if I use a RecursiveIteratorIterator I get the correct values for the first iteration:
$nodes = new ArrayIterator($query);
$iterator = new RecursiveArrayIterator($nodes);
$iteratorIterator = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::LEAVES_ONLY);
print_r(iterator_to_array($iteratorIterator));
Array
(
[name] => Kindle Fire HD
[sale] => 1
[$gt] => 30
[$lt] => 3
[$lte] => 1.2
[0] => US
[1] => CA
)
However, it's of little use since I cannot be sure what $a index the keys are referring to, not to mention that the key values are being overwritten by latter entries and the fact that I can't change their values.
I've also tried playing with RecursiveArrayIterator, but without the hasParent() / getParent() methods it doesn't seem to give me much advantage over simply foreach'ing the array.
Any suggestions?

I quickly read your question it sounds like you want to visit leafs and know the key path to them.
so here:
$ritit = new RecursiveIteratorIterator(new RecursiveArrayIterator($myArray));
foreach ($ritit as $leafValue) {
$keyPath = array();
foreach (range(0, $ritit->getDepth()) as $depth) {
$keyPath[] = $ritit->getSubIterator($depth)->key();
}
// do something with $keyPath
// or
$hasParent = $ritit->getDepth() > 0;
$parentIter = $ritit->getSubIterator($ritit->getDepth() - 1);
$parentKey = $parentIter->key();
}

Related

Ignore empty strings in array_merge [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I have 3 if statements (see code). Each for creating an array of email addresses. How can I merge those 3 strings into a $to (knowing that they could be empty or doesn't even exist)?
Apparently this doesn't work...
if ( in_array('client', $measurement_mail_report_recipients) ) {
$measurement_client_id = intval($_POST['acf']['field_5e147914518a6']);
$list1 = array();
if (have_rows('company_email_addresses', $measurement_client_id)) {
while (have_rows('company_email_addresses', $measurement_client_id)) {
the_row();
$list1[] = get_sub_field('company_email_address');
}
}
}
if ( in_array('contact', $measurement_mail_report_recipients) ) {
$measurement_contact_id = intval($_POST['acf']['field_5e149714d044e']);
$list2 = array();
if (have_rows('contact_email_addresses', $measurement_contact_id)) {
while (have_rows('contact_email_addresses', $measurement_contact_id)) {
the_row();
$list2[] = get_sub_field('contact_email_address');
}
}
}
if ( in_array('extra', $measurement_mail_report_recipients) ) {
$measurement_mail_extra_recipients = $_POST['acf']['field_5f71d4eaaf381'];
if ( $measurement_mail_extra_recipients ) {
$list3 = array();
foreach( $measurement_mail_extra_recipients as $measurement_mail_extra_recipient ) {
$list3[] = $measurement_mail_extra_recipient['field_5f71d55aaf382'];
}
}
}
$to = array_merge($list1, $list2, $list3);
Hopefully this helps you out:
Merge the arrays
Loop through the merged array
Check if current element is "" or null
If so delete it with array_splice()
I know what I forgot. I had to declare the array empty in case the if statement wasn't triggered. Check my working code below:
if ( in_array('client', $measurement_mail_report_recipients) ) {
$measurement_client_id = intval($_POST['acf']['field_5e147914518a6']);
$list1 = array();
if (have_rows('company_email_addresses', $measurement_client_id)) {
while (have_rows('company_email_addresses', $measurement_client_id)) {
the_row();
$list1[] = get_sub_field('company_email_address');
}
}
} else { $list1 = array(); }
if ( in_array('contact', $measurement_mail_report_recipients) ) {
$measurement_contact_id = intval($_POST['acf']['field_5e149714d044e']);
$list2 = array();
if (have_rows('contact_email_addresses', $measurement_contact_id)) {
while (have_rows('contact_email_addresses', $measurement_contact_id)) {
the_row();
$list2[] = get_sub_field('contact_email_address');
}
}
} else { $list2 = array(); }
if ( in_array('extra', $measurement_mail_report_recipients) ) {
$measurement_mail_extra_recipients = $_POST['acf']['field_5f71d4eaaf381'];
if ( $measurement_mail_extra_recipients ) {
$list3 = array();
foreach( $measurement_mail_extra_recipients as $measurement_mail_extra_recipient ) {
$list3[] = $measurement_mail_extra_recipient['field_5f71d55aaf382'];
}
}
} else { $list3 = array(); }
$recipients = array_merge($list1, $list2, $list3);
$to = array_filter($recipients);
$myArray = [];
$myArray2 = [];
// If undefined the value becomes false instead of error (always do this)
$myArray2["value1"] = $_POST["post-value"] ?? false;
// Always use isset to check if a variable is defined
if(isset($myArray["some-value"])){
// do some work
}
// proceed to remove an associated array or any variable
unset($myArray2["value1"]);// You can also unset any variable
PHP isset function returns true if a variable has been defined otherwise false, so use it to check if the array exists. To check if the array has value, use comparison operator like: sth equals another. to delete an associative array or any variable unset it as described above.
//Use this method
$array1 = [0,1,3,6];
$array2 = [];
$array3 = ["a","b","c"];
/*
Store all the collective array in one array
the array_1,2 style will help to resolve things inside for loop
*/
$biggerArray = ["array_1"=>$array1, "array_2"=>$array2, "array_3"=>$array3];
$bigger2 = [];
for($i = 0; $i < 3; $i++){
foreach($biggerArray["$i"] as $k => $v){
if(!$biggerArray["$i"][$k]){
// the value is empty
}else{
// it's not empty
if(!isset($bigger2["array_$i"]){
$bigger2["array_$i"] = [];
}else{
array_push($bigger2["array_$i"],$biggerArray["$i"][$k]);
}
}
}
}
// with function return $bigger2 array

how to remove the curly braces and user_cart string

public function addToCart($id){
$course = Course::findOrfail($id);
$user =Auth::user();
$cart_array = array();
$cart = $user->user_cart;
if ($cart == '') {
array_push($cart_array, array('user_cart' => $course->id));
// print_r($cart_array);
} else {
$founder = false;
$cart_array = json_decode($cart, true);
for ($i = 0; $i < count($cart_array); $i++) {
$cart_for_eacch_course = $cart_array[$i];
if ($cart_for_eacch_course['user_cart'] == $course->id) {
$founder = true;
}
}
if (!$founder) {
array_push($cart_array, array('user_cart' => $course->id));
}
}
$data['user_cart'] = json_encode($cart_array);
$update = User::where('id',$user->id)->update(['user_cart'=> $cart_array]);
Current Output
[{"user_cart":86},{"user_cart":84}]
Expected Output
[84,86]
Now I am having the current Output but I want expected one. I tried by removing the json_encode but it didn't work for me.
You can use array_column() like so
$new_array = array_column($cart_array, 'user_cart');
When you are creating the output array, you are using...
array_push($cart_array, array('user_cart' => $course->id));
which is why you get the sub arrays with the keys. If instead you just add the $course->id values, then this should build the output in the first place rather than having to process it further...
$cart_array[] = $course->id;
You would also need to change the line
if ($cart_for_eacch_course['user_cart'] == $course->id) {
to
if ($cart_for_eacch_course == $course->id) {
as you no longer have the sub index. You could change this part of the code to use in_array() instead which would also be shorter.

Sum up array first, then push into array loop solution

I had a problem with this particular code. The conditions are:
When $rows['Machine#'] is not in array, push in $machineArr array and unset the $totalTimeArr array.
When $rows['Machine#'] is in the array, push $rows['TotalTime'] into $totalTimeArr array for addition.
$graphArr[] should be updated (for array_sum($totalTimeArr)) first before push into array.
only one $graphArr[] for each machine
I now have problems regarding the third condition. It does not calculate first, instead it pushes the first data input. I have tried using do while loop, putting $graphArr[] = '["'.$rows['Machine#'].'",'.array_sum($totalTimeArr).']'; outside the if else loop, but this seems to be the closest I can get to what it's supposed to be. Other codes don't seem to have any problems and work well. Appreciate your recommendations/suggestions/assistance. Below is the code.
while ($rows = mysqli_fetch_array($conn))
{
if(!(in_array($rows['Machine#'], $machineArr)))
{
unset($totalTimeArr);
$machineArr[] = $rows['Machine#'];
$totalTimeArr[] = $rows['TotalTime'];
$graphArr[] = '["'.$rows['Machine#'].'",'.array_sum($totalTimeArr).']';
}
else if(in_array($rows['Machine#'], $machineArr))
{
$totalTimeArr[] = $rows['TotalTime'];
}
}
EDIT: I'm currently on this:
while ($rows = mysqli_fetch_array($conn))
{
$exists = false;
if( in_array($rows['Machine#'], $machineArr) )
{
$exists = true;
}
$totalTimeArr[] = $rows['TotalTime'];
if($exists === false)
{
$totalTimeArr = array();
$machineArr[] = $rows['Machine#'];
$totalTimeArr[] = $rows['TotalTime'];
}
$graphArr[] = '["'.current($machineArr).'",'.array_sum($totalTimeArr).']';
next($machineArr);
}
The result:
Array ( [0] => ["09CS1", 1.4]
[1] => ["08CS1", 1 ]
[2] => ["06CS1", 1 ]
[3] => ["" , 1.5]
[4] => ["02CS2", 1 ]
[5] => ["01CS2", 20 ]
[6] => ["" , 40 ]
[7] => ["01CS1", 1 ]
)
How do I remove ["", 1.5] and ["", 40]?
Below is the database:
I'm not sure what you need to do, if you need a running sum for a specific type of a machine then do something like:
$totalTileArr = [];
while ($rows = mysqli_fetch_array($conn)) {
if (!isset($totalTileArr[$rows['Machine#']])) {
$totalTileArr[$rows['Machine#']] = [];
}
$totalTimeArr[$rows['Machine#']][] = $rows['TotalTime'];
$graphArr[$rows['Machine#']] = '["' . $rows['Machine#'] . '",' . array_sum($totalTimeArr[$rows['Machine#']]) . ']';
}
A slightly modified version of your code cleaned up
$machineArr = Array();
while ($rows = mysqli_fetch_array($conn)) {
$exists = false;
if( in_array($rows['Machine#'], $machineArr) ) { $exists = true; }
$totalTimeArr[] = $rows['TotalTime'];
if($exists === false) {
unset($totalTimeArr);
$machineArr[] = $rows['Machine#'];
$totalTimeArr[] = $rows['TotalTime'];
$graphArr[] = '["'.$rows['Machine#'].'",'.array_sum($totalTimeArr).']';
}
}
Converted the check into one in_array() search, then comparing using === bitwise operator to evaluate the condition. Also defined $machineArr as an Array() as the first check in your loop would always fail given that $machineArr was (presumably as I don't see the code prior to the while loop) undefined.

Recursive Search Function

I have strings that come in the form of "IT/Internet/Web Development/Ajax". I parse it and make a JSON Object like
[{
"name": "IT",
"subcategories":[
{
"name": "Internet",
"subcategories" : [
{
"name": "Web Development",
"subcategories" : [
{
"name":"Ajax"
}]}]}]
I create the JSON object by doing
$input = "IT/Internet/Web Development";
$items = explode("/", $input);
$parent = null;
$firstObject = null;
while (count($items))
{
$object = new StdClass();
$item = array_shift($items);
$object->name = $item;
if (count($items) == 0) {
$object->subcategories=NULL; // I made this null in order to know that this is the last item of the string that comes in
}
if ($parent)
$parent->subcategories = array($object);
else
$firstObject = $object;
$parent = $object;
}
array_push($category_collection, $firstObject); //$category_collection is an array
}
When another string comes in, for example "IT/Internet/Browsers", I want to be able to parse the categories that were created and place "Browsers" in the correct place as a subcategory of Internet, so then my JSON object would look like
[{
"name": "IT",
"subcategories":[
{
"name": "Internet",
"subcategories" : [
{
"name": "Web Development",
"subcategories" : [
{
"name":"Ajax"
}],
{
"name":"Browsers"
}}]}]
I'm having problems writing a recursive function that will just loop the JSON Object to categorize everything in the right place. What I am doing as of right now is
$arrlength = count($category_collection); //count the size of the array
$input = "IT/Internet/Browsers";
$items = explode("/",$input);
$tempVariable = array_shift($items);
$flag = false;
for ($x = 0; $x < $arrlength; $x++) {
//Here I check if the first a category with that name already exists
if ($category_collection[$x]['name'] == $tempVariable) {
$flag = true;
//Now here is where im having problems doing the recursion to check if the subcategory2 already exists and then if subcategory 3 and so on...
}
}
If anybody could guide me on the right direction that would be greatly appreciated
Here is a full function, it should work, you can convert it to json after, if you need:
$categoriesCollection = array();
$input = "IT/Internet/Web Development";
updateCategoriesCollection(explode('/', $input), $categoriesCollection);
$input = "IT/Internet/Browsers";
updateCategoriesCollection(explode('/', $input), $categoriesCollection);
function updateCategoriesCollection(array $categoriesList, array &$categoriesCollection)
{
$name = array_shift($categoriesList);
$category = null;
foreach ($categoriesCollection as $key => $value)
{
if ($value->name == $name)
{
$category = $value;
break;
}
}
if (!$category)
{
$category = new StdClass;
$category->name = $name;
$categoriesCollection[] = $category;
}
if (!empty($categoriesList))
{
if (empty($category->subcategories)) $category->subcategories = array();
updateCategoriesCollection($categoriesList, $category->subcategories);
}
}
var_dump($categoriesCollection);
Output:
Array
(
[0] => stdClass Object
(
[name] => IT
[subcategories] => Array
(
[0] => stdClass Object
(
[name] => Internet
[subcategories] => Array
(
[0] => stdClass Object
(
[name] => Web Development
)
[1] => stdClass Object
(
[name] => Browsers
)
)
)
)
)
)
Try this please (Not tested, maybe some error to correct, i am here to help):
function boolean check_is_good($array, $input)
{
$element = array_shift($input);
for ($x = 0; $x < count($array), $x++) {
if ($array[$x]['name'] == $element){
if ((!isset($array[$x]['subcategories']) && (count($input) == 0))
return (true);
else if ((!isset($array[$x]['subcategories']) && (count($input) != 0))
return (false);
$newArray = $array[$x]['subcategories'];
return (check_is_good($newArray, $input));
}
}
return (false);
}
The function return true is all is in the correct place
You have to pass in parameter1 an array that represent your JSON ($category_collecton in your example)
You have to pass in parameter2 an array with all elements ($items in your example)

How do I redistribute an array into another array of a certain "shape". PHP

I have an array of my inventory (ITEMS A & B)
Items A & B are sold as sets of 1 x A & 2 x B.
The items also have various properties which don't affect how they are distributed into sets.
For example:
$inventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK")
);
I want to redistribute the array $inventory to create $set(s) such that
$set[0] => Array
(
[0] => array(A,PINK)
[1] => array(B,RED)
[2] => array(B,BLUE)
)
$set[1] => Array
(
[0] => array(A,MAUVE)
[1] => array(B,YELLOW)
[2] => array(B,GREEN)
)
$set[2] => Array
(
[0] => array(A,ORANGE)
[1] => array(B,BLACK)
[2] => NULL
)
$set[3] => Array
(
[0] => array(A,GREY)
[1] => NULL
[2] => NULL
)
As you can see. The items are redistributed in the order in which they appear in the inventory to create a set of 1 x A & 2 x B. The colour doesn't matter when creating the set. But I need to be able to find out what colour went into which set after the $set array is created. Sets are created until all inventory is exhausted. Where an inventory item doesn't exist to go into a set, a NULL value is inserted.
Thanks in advance!
I've assumed that all A's come before all B's:
$inventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK")
);
for($b_start_index = 0;$b_start_index<count($inventory);$b_start_index++) {
if($inventory[$b_start_index][0] == 'B') {
break;
}
}
$set = array();
for($i=0,$j=$b_start_index;$i!=$b_start_index;$i++,$j+=2) {
isset($inventory[$j])?$temp1=$inventory[$j]:$temp1 = null;
isset($inventory[$j+1])?$temp2=$inventory[$j+1]:$temp2 = null;
$set[] = array( $inventory[$i], $temp1, $temp2);
}
To make it easier to use your array, you should make it something like this
$inv['A'] = array(
'PINK',
'MAUVE',
'ORANGE',
'GREY'
);
$inv['B'] = array(
'RED',
'BLUE',
'YELLOW',
'GREEN',
'BLACK'
);
This way you can loop through them separately.
$createdSets = $setsRecord = $bTemp = array();
$bMarker = 1;
$aIndex = $bIndex = 0;
foreach($inv['A'] as $singles){
$bTemp[] = $singles;
$setsRecord[$singles][] = $aIndex;
for($i=$bIndex; $i < ($bMarker*2); ++$i) {
//echo $bIndex.' - '.($bMarker*2).'<br/>';
if(empty($inv['B'][$i])) {
$bTemp[] = 'null';
} else {
$bTemp[] = $inv['B'][$i];
$setsRecord[$inv['B'][$i]][] = $aIndex;
}
}
$createdSets[] = $bTemp;
$bTemp = array();
++$bMarker;
++$aIndex;
$bIndex = $bIndex + 2;
}
echo '<pre>';
print_r($createdSets);
print_r($setsRecord);
echo '</pre>';
To turn your array into an associative array, something like this can be done
<?php
$inventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK")
);
$inv = array();
foreach($inventory as $item){
$inv[$item[0]][] = $item[1];
}
echo '<pre>';
print_r($inv);
echo '</pre>';
Maybe you can use this function, assuming that:
... $inventory is already sorted (all A come before B)
... $inventory is a numeric array staring at index zero
// $set is the collection to which the generated sets are appended
// $inventory is your inventory, see the assumptions above
// $aCount - the number of A elements in a set
// $bCount - the number of B elements in a set
function makeSets(array &$sets, array $inventory, $aCount, $bCount) {
// extract $aItems from $inventory and shorten $inventory by $aCount
$aItems = array_splice($inventory, 0, $aCount);
$bItems = array();
// iterate over $inventory until a B item is found
foreach($inventory as $index => $item) {
if($item[0] == 'B') {
// extract $bItems from $inventory and shorten $inventory by $bCount
// break out of foreach loop after that
$bItems = array_splice($inventory, $index, $bCount);
break;
}
}
// append $aItems and $bItems to $sets, padd this array with null if
// less then $aCount + $bCount added
$sets[] = array_pad(array_merge($aItems, $bItems), $aCount + $bCount, null);
// if there are still values left in $inventory, call 'makeSets' again
if(count($inventory) > 0) makeSets($sets, $inventory, $aCount, $bCount);
}
$sets = array();
makeSets($sets, $inventory, 1, 2);
print_r($sets);
Since you mentioned that you dont have that much experience with arrays, here are the links to the php documentation for the functions I used in the above code:
array_splice — Remove a portion of the array and replace it with something else
array_merge — Merge one or more arrays
array_pad — Pad array to the specified length with a value
This code sorts inventory without any assumption on inventory ordering. You can specify pattern (in $aPattern), and order is obeyed. It also fills lacking entries with given default value.
<?php
# config
$aInventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK"),
array("C","cRED"),
array("C","cBLUE"),
array("C","cYELLOW"),
array("C","cGREEN"),
array("C","cBLACK")
);
$aPattern = array('A','B','A','C');
$mDefault = null;
# preparation
$aCounter = array_count_values($aPattern);
$aCurrentCounter = $aCurrentIndex = array_fill_keys(array_unique($aPattern),0);
$aPositions = array();
$aFill = array();
foreach ($aPattern as $nPosition=>$sElement){
$aPositions[$sElement] = array_keys($aPattern, $sElement);
$aFill[$sElement] = array_fill_keys($aPositions[$sElement], $mDefault);
} // foreach
$nTotalLine = count ($aPattern);
$aResult = array();
# main loop
foreach ($aInventory as $aItem){
$sElement = $aItem[0];
$nNeed = $aCounter[$sElement];
$nHas = $aCurrentCounter[$sElement];
if ($nHas == $nNeed){
$aCurrentIndex[$sElement]++;
$aCurrentCounter[$sElement] = 1;
} else {
$aCurrentCounter[$sElement]++;
} // if
$nCurrentIndex = $aCurrentIndex[$sElement];
if (!isset($aResult[$nCurrentIndex])){
$aResult[$nCurrentIndex] = array();
} // if
$nCurrentPosition = $aPositions[$sElement][$aCurrentCounter[$sElement]-1];
$aResult[$nCurrentIndex][$nCurrentPosition] = $aItem;
} // foreach
foreach ($aResult as &$aLine){
if (count($aLine)<$nTotalLine){
foreach ($aPositions as $sElement=>$aElementPositions){
$nCurrentElements = count(array_keys($aLine,$sElement));
if ($aCounter[$sElement] != $nCurrentElements){
$aLine = $aLine + $aFill[$sElement];
} // if
} // foreach
} // if
ksort($aLine);
# add empty items here
} // foreach
# output
var_dump($aResult);
Generic solution that requires you to specify a pattern of the form
$pattern = array('A','B','B');
The output will be in
$result = array();
The code :
// Convert to associative array
$inv = array();
foreach($inventory as $item)
$inv[$item[0]][] = $item[1];
// Position counters : int -> int
$count = array_fill(0, count($pattern),0);
$out = 0; // Number of counters that are "out" == "too far"
// Progression
while($out < count($count))
{
$elem = array();
// Select and increment corresponding counter
foreach($pattern as $i => $pat)
{
$elem[] = $inv[ $pat ][ $count[$i]++ ];
if($count[$i] == count($inv[$pat]))
$out++;
}
$result[] = $elem;
}

Categories