I need some help with generation of combinations, specifically in the store they're the variants of each product, e.g size and colour.
Let's say we have 3 customizable properties of the product:
Colour, Size, and Type.
For this specific product, the following are available of each property:
Color: [red, green], Size: [10, 11, 15], Type: [person]
Now according to the above data, I need to generate 6 combinations, however if we added another type it would increase even more.
I have been drawing on my board for 2 hours now trying to come up with a sane algorithm for this, something that's fast and can deal with thousands of combinations in a matter of seconds.
Take this example:
$options = ['Color' => ['Red', 'Green'], 'Size' => ['10', '11', '15'], 'Type' => ['person']];
$combinations = generateCombinations($options);
genereateCombinations would then need to generate the following output:
[
['Color' => 'Red', 'Size' => '10', 'Type' => 'person'],
['Color' => 'Red', 'Size' => '11', 'Type' => 'person'],
['Color' => 'Red', 'Size' => '15', 'Type' => 'person'],
['Color' => 'Green', 'Size' => '10', 'Type' => 'person'],
['Color' => 'Green', 'Size' => '11', 'Type' => 'person'],
['Color' => 'Green', 'Size' => '15', 'Type' => 'person']
];
What algorithm could do this efficiently and with unlimited input "titles"? (of course I'll enforce a limit earlier, but the algorithm should be able to do unlimited granted all the resources in the world)
Extending what I mean:
This function also needs to be able to take for example an array with 100 property rows, not just 3, it needs to be able to do this dynamically no matter the number of input rows.
Three foreach loops are enough to generate all combinations, no matter how many entries are in $options:
function generateCombinations(array $options)
{
// Start with one combination of length zero
$all = array(array());
// On each iteration append all possible values of the new key
// to all items in $all; generate this way all the combinations
// one item longer than before
foreach ($options as $key => $values) {
// Move all combinations of length N from $all to $current
$current = $all;
// Start with an empty list of combinations of length N+1
$all = array();
// Combine each combination of length N
// with all possible values for the (N+1)th key
foreach ($current as $one) {
foreach ($values as $val) {
// Put each new combination in $all (length N+1)
$all[] = array_merge($one, array($key => $val));
}
}
}
return $all;
}
$options = [
'Color' => ['Red', 'Green'],
'Size' => ['10', '11', '15'],
'Type' => ['person'],
'Answer' => ['Yes', 'No'],
];
$combinations = generateCombinations($options);
echo(count($combinations));
# 12
It can probably be slightly improved but, all in all, if you don't know in advance the length of $options it does a lot of duplicate iterations. If you know in advance the number of items in $options (let's say it is N) then N nested loops are the fast way to do it.
Related
Note
This question is NOT a duplicate of
Filtering multi-dimensional array
Filter out empty array elements of multidimensional array
or several other related questions
I have a very peculiar use case where I have to filter a multi-dimensional array 'inwards to outwards', implying
"filter the innermost level elements, then it's preceding level
elements and so on until coming to filtering the topmost level"
As an (dummy, mock) example, consider this
suppose we have a nested of restaurant-ids (res_ids) grouped by countries (1, 2, & 3) & cities (11, 12, 21, 22, 23, 31)
[
1 => [
11 => [
111 => ['res_id' => 111, 'city_id' => 11, 'country_id' => 1],
112 => ['res_id' => 112, 'city_id' => 11, 'country_id' => 1],
113 => ['res_id' => 113, 'city_id' => 11, 'country_id' => 1],
],
12 => [
121 => ['res_id' => 121, 'city_id' => 12, 'country_id' => 1],
],
],
2 => [
21 => [
212 => ['res_id' => 212, 'city_id' => 21, 'country_id' => 2],
214 => ['res_id' => 214, 'city_id' => 21, 'country_id' => 2],
],
22 => [
221 => ['res_id' => 221, 'city_id' => 22, 'country_id' => 2],
222 => ['res_id' => 222, 'city_id' => 22, 'country_id' => 2],
223 => ['res_id' => 223, 'city_id' => 22, 'country_id' => 2],
],
],
3 => [
31 => [
312 => ['res_id' => 312, 'city_id' => 21, 'country_id' => 2],
314 => ['res_id' => 314, 'city_id' => 21, 'country_id' => 2],
],
]
]
and we want to remove all restaurants (plus the parent sub-array structure) having even res_ids (keep odd ones)
so that resulting output nested array is as follows
note that not only individual 'leaf' items depicting res have been filtered, but also higher level city and country items have been filtered if they contained only even res_ids (which we intended to remove)
[
1 => [
11 => [
111 => ['res_id' => 111, 'city_id' => 11, 'country_id' => 1],
113 => ['res_id' => 113, 'city_id' => 11, 'country_id' => 1],
],
12 => [
121 => ['res_id' => 121, 'city_id' => 12, 'country_id' => 1],
],
],
2 => [
22 => [
221 => ['res_id' => 221, 'city_id' => 22, 'country_id' => 2],
223 => ['res_id' => 223, 'city_id' => 22, 'country_id' => 2],
],
],
]
actually i myself created above array from a flat array by recursive grouping; but now I have to filter them in groups (which can't be done before grouping)
While i can certainly do this using nested loops, I was wondering if we can create a generic function for it (i have other such multi-dimensional filtering use-cases at different depths across my project)
Another important thing to note here that given the generic filtering criteria requirement, we would ideally like to be able to have a different filtering criteria per level: custom functions per se.
Any ideas?
You can do this lika a array_filter callback.
$currentKey is not required, but may be handy.
Working example.
function array_filter_clean(array $array, array $callbacks, $currentDepth = 0, $currentKey = '') {
if (array_key_exists($currentDepth, $callbacks)) { // identify node to apply callback to
$callback = $callbacks[$currentDepth];
if (!$callback($currentKey, $array)) { // empty node when callback returns false (or falsy)
return [];
}
}
foreach ($array as $key => &$value) { // &value to modify $array
if (is_array($value)) {
$value = array_filter_clean($value, $callbacks, $currentDepth+1, $key); // recurse if array
}
}
return array_filter($array); // remove empty nodes (you may want to add "afterCallbacks" here)
}
$callbacksByDepth = [
/* 2 => function ($key, $value) {
return $key > 20;
}, */ // test
3 => function ($key, $value) {
return $value['res_id']%2;
},
];
$output = array_filter_clean($input, $callbacksByDepth);
print_r($output);
I've added comments - in case i forgot to explain something please let me know.
Worth mentioning
This can be done with an extension of RecursiveFilterIterator within a RecursiveIteratorIterator - but the readability of the provided solution is far superior.
Note
Given the case you want to keep every node which contains at least 3 items after you've applied your callback, you will have to extend this funtion (at the last line). You could do exactly the same like above array_key_exists($currentDepth, $callbacksXXX) for another $callbacksAfter array with the same structure. (Or build everything in one array and key your callbacks with before and after - up to you)
I came up with following function that accepts a list of callables, each one of which is used for filtering the array at a single level
in-line with the original example, filtering is done 'inwards to outwards': first we filter the innermost level, then the one above that and so on (so essentially the nth filter acts on residual output obtained by applying n-1 filters before it)
have a look at the unit-tests to understand the behaviour
/**
* Filters a multi-dimensional array recursively by applying series of filtering function callables, each at a
* different level. Filtering is done starting from innermost depth and moving outwards.
* It is assumed that structure / depth of array is consistent throughout (each key grows upto same max depth)
*
* Regarding $filter_callables
* - this is a series of filtering functions (callables) applied at each level (1st callable is for first /
* top-most or outer-most level, next callable is for next level at depth 2 and so on)
* - each filter callable function should accept exactly 2 arguments: (1) the value or item and (2) the key of item
* as mandated by 'ARRAY_FILTER_USE_BOTH' flag of PHP's array_filter function
* - to skip applying filtering at a level, we can pass null (instead of callable) for that position
* - no of callables should be less than or equal to depth of array (or else exception will be thrown)
*
* see test-cases to understand further (plus detailed explaination)
* #param array $nested_array Nested array to be filtered resursively
* #param array $filter_callables List of callables to be used as 'filter' functions at each 'depth' level
* #return array Recursively filtered array
*/
public static function filterByFnRecursive(array $nested_array, array $filter_callables): array {
if (empty($nested_array) || empty($filter_callables)) {
// base case: if array is empty (empty array was passed) or no more callables left to be applied, return
return $nested_array;
} else {
// retrieve first callable (meant for this level)
$filterer = array_shift($filter_callables);
if (!empty($filter_callables)) {
// if there are more callables, recursively apply them on items of current array
$modified_nested_array = array_map(static function (array $item) use ($filter_callables): array {
return self::filterByFnRecursive($item, $filter_callables);
}, $nested_array);
} else {
// otherwise keep the current array intact
$modified_nested_array = $nested_array;
}
if (empty($filterer)) {
// if callable is NULL, return array (at current level) unmodified
// this is provided to allow skipping filtering at any level (by passing null callable)
return $modified_nested_array;
} else {
// otherwise filter the items at current level
return array_filter($modified_nested_array, $filterer, ARRAY_FILTER_USE_BOTH);
}
}
}
Do checkout this gist for bigger collection of array utility functions along with unit-tests
How Can I Create a main array that includes multiple child array And be in the form of Jason and I want to add the child Array to main array in the Loop
MainArray=[
array1=[{fname:asdada,lastname:sdsadasda}];
array2=[{fname:asdada,lastname:sdsadasda}];
array3=[{fname:asdada,lastname:sdsadasda}];
];
echo MainArray[1]->fname;
Please see the following pseudo code below:
pseudo code
You should really look into a basic php tutorial.
This is how you do it.
$mainArray = [
'array1' => ['fname' => 'asdada', 'lastname' => 'sdsadasda'],
'array2' => ['fname' => 'asdada', 'lastname' => 'sdsadasda'],
'array3' => ['fname' => 'asdada', 'lastname' => 'sdsadasda']
];
echo $mainArray['array1']['fname'];
Or use the long notation if you have an older version of php or want backwards compatibility.
$mainArray = array(
'array1' => array('fname' => 'foo', 'lastname' => 'bar'),
'array2' => array('fname' => 'lorem', 'lastname' => 'ipsum'),
'array3' => array('fname' => 'test', 'lastname' => 'example')
);
echo $mainArray['array1']['fname'];
Explanation:
The php variable sigil is $. This means that in order to access a variable or assign something to a variable, you use $mainArray. See more on variables in the documentation.
The php array can be used in two different notations. Either array(...) or, from php 5.4 upwards, [...]. Other than the opening and closing parts, they are identical. You don't use : or = to assign individual values inside an array declaration. For this you use the => operator. Each element in an array is separated by a comma (,).
E.g.
$mainArray = array(
'A' => 1,
'B' => 2
];
Arrays in Php can be either associative or numerical. What you probably want is that your outer array is numerical, meaning you can access it using $mainArray[1], and your inner array is associative. For numerical arrays, you don't specify a key yourself, so there is no need for the =>.
$mainArray = array(
array(),
array(),
array()
);
And with associative sub arrays this becomes:
$mainArray = array(
array('firstname' => 'foo', 'lastname' => 'bar'),
array('firstname' => 'test', 'lastname' => 'example'),
array('firstname' => 'lorem', 'lastname' => 'ipsum')
);
In order to access the firstname key of the first child array in this multilevel array structure, you do:
$mainArray[0]['firstname']
E.g. (if you want to echo it to the standard output)
echo $mainArray[0]['firstname'];
Please note that numerical arrays in php start counting on 0, as in most other programming languages. And please note that the key in the associative array is a string, and as such must be surrounded with either ' or ".
I can recommend you search for a php beginner's tutorial and try to write and execute the examples yourself, to get a better grasp of php. If you need somewhere to run your php examples, I can recommend you try an online php environment such as PHPFiddle.
Update on adding values:
You can add more key=>value pairs to an associative array or add more values to a numerical array afterwards in much the same way as you would access or assign to it.
First, let's add a value to a numerical array. You do this by adding [] to the end of your variable when assigning. This means that what you assign will be added as a new numerical value to the end of your array.
$numericalArray = array(
7,
8,
6,
12,
'B'
);
$numericalArray[] = 'C';
// Results in the array: array(7, 8, 6, 12, 'B', 'C')
And in order to add a new key => value pair to an associative array, you just add it using the new key, e.g.
$assoc = array(
'firstname' => 'Testy',
'lastname' => 'McTestface'
);
$assoc['middlename'] => 'Tester';
So to add a new fname-lastname pair to the mainArray, you would do:
$mainArray = array(
array('fname' => 'foo', 'lastname' => 'bar'),
array('fname' => 'test', 'lastname' => 'example'),
array('fname' => 'lorem', 'lastname' => 'ipsum')
);
$mainArray[] = array('fname' => 'new name', 'lastname' => 'new last name');
If you want to do this in a loop, you will use the for, foreach, while or do while structures.
E.g.
$mainArray = array(
array('fname' => 'foo', 'lastname' => 'bar'),
array('fname' => 'test', 'lastname' => 'example'),
array('fname' => 'lorem', 'lastname' => 'ipsum')
);
for ($i = 0; $i < 3; ++$i) {
$mainArray[] = array('fname' => 'new name ' . $i, 'lastname' => 'new last name ' . $i);
}
echo json_encode($mainArray, JSON_PRETTY_PRINT|JSON_UNESPACED_UNICODE|JSON_UNESCAPED_SLASHES), PHP_EOL;
// [
// {'fname': 'foo', 'lastname': 'bar'},
// {'fname': 'test', 'lastname': 'example'},
// {'fname': 'lorem', 'lastname': 'ipsum'},
// {'fname': 'new name 0', 'lastname': 'new last name 0'},
// {'fname': 'new name 1', 'lastname': 'new last name 1'},
// {'fname': 'new name 2', 'lastname': 'new last name 2'},
// ]
I have two arrays, that I want to merge as one according to keys suffix.
$keys = array(
'staff_first_name' => NULL,
'staff_last_name' => NULL,
'staff_years' => NULL
);
$submitted_values = array(
'first_name' => 'jon',
'last_name' => 'doe',
'years' => 5
);
I understand I could use a function like shown here and modify it.
But is there a native php function that will accomplish this. I attempted to use array_merge_recursive but after reviewing the documentation It will not do what I need it to.
$wanted_array = array(
'staff_first_name' => 'jon',
'staff_last_name' => 'doe',
'staff_years' => 5
);
If you know the two arrays are the same size, and in the same order, you can use array_combine with array_keys.
$wanted_array = array_combine(array_keys($keys), $submitted_values);
Because it's a suffix that is the same on each key we don't need to worry about it.
If we ksort the arrays they should both be sorted the same because the suffix is the same on all in key array.
$keys = array(
'staff_first_name' => NULL,
'staff_last_name' => NULL,
'staff_years' => NULL
);
$values = array(
'years' => 5,
'first_name' => 'jon',
'last_name' => 'doe',
);
ksort($values);
ksort($keys);
Var_dump(array_combine(array_keys($keys), $values));
I intentionally placed years first to show that it works.
https://3v4l.org/cBNhk
If you need to reduce the $_POST to only these array items to be able to combine them you can use a combination of preg_grep, array_flip, array_values and array_intersect_key to filter out the wanted items from the array.
$val = preg_grep("/first_name|last_name|years/",array_values(array_flip($values)));
$values = Array_intersect_key($values, array_flip($val));
ksort($values);
ksort($keys);
Var_dump(array_combine(array_keys($keys), $values));
I added some extra items to simulate a larger mixed $_POST array.
https://3v4l.org/a3ju1
This is one of those questions where I must implore the OP to rethink their process. It only complicates your code to introduce associative keys that do not instantly synchronize with your form field names. This is the best advice that I can give you: declare a whitelist of keys and assign default values to each, then filter, then replace.
Since your values are all null, your code can be made more DRY by calling array_fill_keys().
The following can be written as one line of code, but to show each step, I've printed the arrays to screen after each function call.
Code: (Demo)
$defaults = array_fill_keys(['first_name', 'last_name', 'years'], null);
var_export($defaults);
$_GET = [
'last_name' => 'doe',
'Hackers' => 'can be naughty',
'years' => 5
];
var_export($_GET);
$screened = array_intersect_key($_GET, $defaults);
var_export($screened);
$replaced = array_replace($defaults, $screened);
var_export($replaced);
Output:
array (
'first_name' => NULL,
'last_name' => NULL,
'years' => NULL,
)array (
'last_name' => 'doe',
'Hackers' => 'can be naughty',
'years' => 5,
)array (
'last_name' => 'doe',
'years' => 5,
)array (
'first_name' => NULL,
'last_name' => 'doe',
'years' => 5,
)
...p.s. makes sure that you use prepared statements with placeholders if you are sending any of the values to the database.
I am reading an excell file with php. No problem with that but I am stuck on a little logical part. I want to make an array that containts multiple other arrays with data.
The data is provided in my excell file I know from what column should start reading but not when to stop because this is dynamic.
My question is how can a make a loop that reads my columns and makes on every 5th column a new array.
so what I want is something like this:
(My data for the excell file is proved in $line[] each column has its number.)
array(
'length' => $line[15],
'width' => $line[16]
'price_per' => $line[17],
'price' => $line[18],
'stock' => $line[19]
),
array(
'length' => $line[20],
'width' => $line[21]
'price_per' => $line[22],
'price' => $line[23],
'stock' => $line[24]
),
array(
'length' => $line[25],
'width' => $line[26]
'price_per' => $line[27],
'price' => $line[28],
'stock' => $line[29]
), ....
So how can I make this dynamic (for loop ?) so that I have 1 big indexed Array , with multiple asscociated arrays? Note: my for loop should always star from line[15]!
To begin with, if $line has any elements that you don't want to process (e.g. the first 15 as your example indicates), slice them off with array_slice:
$line = array_slice($line, 15);
Then use array_chunk to split your original array into as many pieces as there are:
$chunks = array_chunk($line, 5);
Then, turn each chunk into its own array by associating each value with the correct key using array_combine:
$results = array();
$keys = array('length', 'width', 'price_per', 'price', 'stock');
foreach ($chunks as $chunk) {
$results[] = array_combine($keys, $chunk);
}
for($i = 15; $i < ????; $i += 5)
{
$your_array[] = array(
'length' => $line[$i],
'width' => $line[$i+1]
'price_per' => $line[$i+2],
'price' => $line[$i+3],
'stock' => $line[$i+4]
);
}
Replace ???? by the number of lines
I have a database table as follows:
This returns all column titles in the pic, but the one's that are most important are slug, and parent (not sure about id_button).
The array gets ordered automatically by id_button ASC, which really irks me. But, anyways, this is not important, as I need to order it completely different, or re-order it after the array is populated.
The array returns this, by order of id_button:
$new_menu_buttons = array(
0 => array(
'id_button' => 1,
'parent' => 'help',
'position' => 'child_of',
'slug' => 'testing',
),
1 => array(
'id_button' => 2,
'parent' => 'packages',
'position' => 'after',
'slug' => 'sub_test_1',
),
2 => array(
'id_button' => 3,
'parent' => 'google.com',
'position' => 'after',
'slug' => 'another_test',
),
3 => array(
'id_button' => 4,
'parent' => 'testing'
'position' => 'child_of',
'slug' => 'google.com',
)
);
I need to order it so that if a slug is found within any parent, than the slug that is in the parent needs to be loaded before the one that has it defined within the parent.
Its not important if it is directly before it. For example, you see testing is the first slug that gets returned, and yet the parent for this is the last slug (google.com). So as long as the slug row where the parent is defined gets ordered so that it is BEFORE the row that has the slug value in the parent column, everything is fine.
So in this situation, it can be reordered as any of these 3 ordered arrays below:
$new_menu_buttons = array(
0 => array(
'id_button' => 1,
'parent' => 'help',
'position' => 'child_of',
'slug' => 'testing',
),
1 => array(
'id_button' => 2,
'parent' => 'packages',
'position' => 'after',
'slug' => 'sub_test_1',
),
2 => array(
'id_button' => 4,
'parent' => 'testing',
'position' => 'child_of',
'slug' => 'google.com',
),
3 => array(
'id_button' => 3,
'parent' => 'google.com'
'position' => 'after',
'slug' => 'another_test',
)
);
OR this...
$new_menu_buttons = array(
0 => array(
'id_button' => 1,
'parent' => 'help',
'position' => 'child_of',
'slug' => 'testing',
),
1 => array(
'id_button' => 4,
'parent' => 'testing',
'position' => 'child_of',
'slug' => 'google.com',
),
2 => array(
'id_button' => 2,
'parent' => 'packages',
'position' => 'after',
'slug' => 'sub_test_1',
),
3 => array(
'id_button' => 3,
'parent' => 'google.com'
'position' => 'after',
'slug' => 'another_test',
)
);
OR even this...
$new_menu_buttons = array(
0 => array(
'id_button' => 1,
'parent' => 'help',
'position' => 'child_of',
'slug' => 'testing',
),
1 => array(
'id_button' => 4,
'parent' => 'testing',
'position' => 'child_of',
'slug' => 'google.com',
),
2 => array(
'id_button' => 3,
'parent' => 'google.com'
'position' => 'after',
'slug' => 'another_test',
),
3 => array(
'id_button' => 2,
'parent' => 'packages',
'position' => 'after',
'slug' => 'sub_test_1',
)
);
All 3 of these ordered arrays will work because the array with the slug that matches the parent is before the array with the matching parent, and since the slug value, sub_test_1 doesn't match any of the parent values this array order is unimportant, so that array can be located anywhere within the array.
How can I do this? I'm thinking of just looping through the array somehow and trying to determine if the slug is in any of the parents, and just do a reordering somehow...
In short, the slug needs to be ordered before the parent ONLY if there is a parent that matches a slug within the array. Otherwise, if no match is found, the order isn't important.
As Niko suggested, databases support powerful sorting functionality, so you normally can best solve this by telling the database in which order to return the data. If the data is queried with SQL, that's the ORDER BY clause. This is specified in the documentation of your database, assuming you're using MySQL 5.0: http://dev.mysql.com/doc/refman/5.0/en/sorting-rows.html
If you can not influence the order on the database level, you're in the need to sort the array in PHP. You actually have an array of arrays, in which the outer array is just a list having the id (primary key) of each row and the other fields as a fieldname -> value array as a value (inner array).
Your sort is *user-defined` - you specify the sort order. A common way is to have a sort function that compares two entries which each other. That sort function needs to decide which of those two is of a higher sort-order than the other (or both have the same weight). In you case one item is higher than the other if one is the child of the other.
That's the general principle. You define the sort function that decides (the so called callback function), and PHP takes care to feed it with the array data to sort with the usortDocs function.
A sub-problem you need to solve then is to decide whether or not a child exists in the whole array (an item with a slug having the same value as parent). As this all looks like it can be a bit more complex, it's wise to encapsulate this all into a class of it's own.
Example / Demo:
class menuButtons
{
/**
* #var array
*/
private $buttons;
public function __construct(array $buttons)
{
$this->buttons = $buttons;
}
public function sortChildsFirst()
{
$buttons = $this->buttons;
usort($buttons, array($this, 'sortCallback'));
return $buttons;
}
private function sortCallback($a, $b)
{
// an element is more than any other if it's parent
// value is any other slugs value
if ($this->slugExists($a['parent']))
return 1;
return -1;
}
private function slugExists($slug)
{
foreach($this->buttons as $button)
{
if ($button['slug'] === $slug)
return true;
}
return false;
}
}
$buttons = new menuButtons($new_menu_buttons);
$order = $buttons->sortChildsFirst();
Note: This code is exploiting the fact that your sort order is only roughly specified. You only wrote that you need to have children before parents, so if you take all children first, this will always be the case. It's not that each parent will directly follow the child.
Nevertheless, this skeleton class can work as a base to further improve the search functionality as it's fully encapsulated. You can even change the whole sort method, e.g. to completely write one of your own even w/o usort, like outlined below. The main code does not need to change as it's only making use of the sortChildsFirst method.
You can sort an array once populated using the usort() function.
http://php.net/manual/en/function.usort.php
Since your structure is tree-alike, the first thing that comes to mind is to build a tree out of it. It goes like this:
$tree = array();
foreach($array as $e) {
$p = $e['parent'];
$s = $e['slug'];
if(!isset($tree[$p]))
$tree[$p] = new stdclass;
if(!isset($tree[$s]))
$tree[$s] = new stdclass;
$tree[$s]->data = $e;
$tree[$p]->sub[] = $tree[$s];
}
This creates a set of objects, with the members data and sub = list of child objects.
Now we iterate the tree and for each "root" node, add it and its children to the sorted array:
$out = array();
foreach($tree as $node)
if(!isset($tree[$node->data['parent']]))
add($out, $node);
where add() is
function add(&$out, $node) {
if(isset($node->data))
$out[] = $node->data;
if(isset($node->sub))
foreach($node->sub as $n)
add($out, $n);
}
hope this helps.
Ok, first let me thank you all for your detailed explanations. They are very intuitive. However, I found another way, can you guys let me know if you spot anything wrong with this method here please?
Click here to see a Demo of this working!
$temp_buttons = array();
foreach($new_menu_buttons as $buttons)
$temp_buttons[$buttons['parent']] = $buttons['slug'];
dp_sortArray($new_menu_buttons, $temp_buttons, 'slug');
// The $new_menu_buttons array is now sorted correctly! Let's check it...
var_dump($new_menu_buttons);
function dp_sortArray(&$new_menu_buttons, $sortArray, $sort)
{
$new_array = array();
$temp = array();
foreach ($new_menu_buttons as $key => $menuitem)
{
if (isset($sortArray[$menuitem[$sort]]))
{
$new_array[] = $menuitem;
$temp[$menuitem['parent']] = $menuitem['slug'];
unset($new_menu_buttons[$key]);
}
}
$ordered = array();
if (!empty($new_array))
{
foreach ($new_array as $key => $menuitem)
{
if (isset($temp[$menuitem[$sort]]))
{
$ordered[] = $menuitem;
unset($new_array[$key]);
}
}
}
else
{
$new_menu_buttons = $new_menu_buttons;
return;
}
$new_menu_buttons = array_merge($ordered, $new_array, $new_menu_buttons);
}
Seems to work in all instances that I tested, but ofcourse, their could be a flaw in it somewhere. What do you all think of this?