Generate all combinations of elements between arrays - php

I have multiple arrays that contain multiple elememts, for example:
$array1 = (1,2)
$array2 = (3,4)
I need to generate all possible combinations for elements of arrays. For given example, the output should be:
1_3, 1_4, 2_3, 2_4
However, the issue is that both number of arrays and amount of elements in each one can be different. So we can also take something like that:
$array1 = (1,2,3,4)
$array2 = (5,6,7)
$array3 = (8,9,10,11,12)
and output should look like that:
1_5_8, 1_5_9, 1_5_10 etc. until 4_7_12.
How do I implement something like that? I know that I should use foreach loop, but I have no idea what to do if amount of "foreaches" can be different every time I execute algorithm.
Any help is really appreciated :)

<?php
$array1 = [1,2,3,4];
$array2 = [5,6,7];
$array3 = [8,9,10,11,12];
$collection = [$array1,$array2,$array3];
$result = $collection[0];
array_shift($collection);
foreach($collection as $each_array){
$temp = [];
foreach($result as $each_sub_result){
foreach($each_array as $each_item){
$temp[] = $each_sub_result."_".$each_item;
}
}
$result = $temp;
}
print_r($result);
Algorithm:
We collect all arrays in our $collection variable.
Now, we loop over all elements of our $collection variable where each individual item is an array.
I have done an array_shift() since we are assigning first element of $collection to $result(so we don't want to iterate over them again).
We maintain $temp to store temporary results. Note that we use $result also to store temporary results, so that we can iterate over it and get new temporary results. By temporary, I mean building the final array. For example: It starts with 1, then 1_5 and then finally 1_5_8.
After the looping completes, we will have our final answer in $result.

try something like this:
$array1 = array(1,2,3);
$array2 = array(4,5,6);
foreach ($array1 as $a1){
foreach ($array2 as $a2){
echo $a1 . '_' . $a2 . ', ';
}
}
You can expand it like you wish.

I'm good in JS so that's why I did the algo in JS, you can try to do this in PHP,,no much difficult. You just have to pass in all the array is the function and the rest should be done by itself. Let me know if any confusions.
var arr1 = [1, 2, 3];
var arr2 = [4, 5];
var arr3 = [6, 7, 8];
var numberOfArrays = -1;
function processArrays(concatWith = [], allArrays) {
const duplicateArray = [...allArrays];
for (var i = 0; i < allArrays.length; i++) {
const currentArray = duplicateArray.splice(0, 1);
currentArray[0].forEach(function (value) {
concatWith.push(value);
processArrays(concatWith, duplicateArray);
if (concatWith.length === numberOfArrays) {
console.log(concatWith.join('_'));
}
concatWith.pop();
});
}
}
function makeCombinations(arrayOfAllArrays = []) {
numberOfArrays = arrayOfAllArrays.length;
processArrays([], arrayOfAllArrays);
}
makeCombinations([arr1, arr2, arr3]);

Related

PHP create 1 array of 4 arrays ordered by index

I have 4 arrays, each one holds another column of a table, I would like to create one array with the data ordered per array[$i]. All arrays have the same number of values: $namesArr, $folderArr, $updatedAt, $valuesArr .
I would like my new array to be contain:
$namesArr[0], $folderArr[0], $updatedAt[0], $valuesArr[0],
$namesArr[1], $folderArr[1], $updatedAt[1], $valuesArr[1],
$namesArr[2], $folderArr[2], $updatedAt[2], $valuesArr[2],
...
I guess the solution is pretty simple, but I got stuck :(
Can anyone help?
I would do something like:
$arr = array_map(function () { return func_get_args(); },$namesArr, $folderArr, $updatedAt, $valuesArr);
You can use foreach loop to merge 4 arrays:
foreach ($namesArr as $key => $value) {
$arr[$key][] = $value;
$arr[$key][] = $folderArr[$key];
$arr[$key][] = $updatedAt[$key];
$arr[$key][] = $valuesArr[$key];
}
Thus $arr will be the merged array
<?php
$newArr = array();
for ($i = 0; $i < count($namesArr); $i++)
{
$newArr[$i][0] = $namesArr[$i];
$newArr[$i][1] = $folderArr[$i];
$newArr[$i][2] = $updatedAt[$i];
$newArr[$i][3] = $valuesArr[$i];
}
?>
Explanation
What this will do is iterate depending on how many elements there are in $namesArr.
I utilised a multidimensional array here so that the first set of square brackets is effectively the "row" in a table, and the second set of square brackets are the "column" of a table.
do the following way:
while($db->query($sql)){
$namesArr[] =$db->f('names');
$folderArr[]=$db->f('folder');
$updatedAt[]=$db->f('updated');
$valuesArr[]=$db->f('values');
}

Merging json files together in php

I'm iterating over a directory and merging the JSON-Files in it. But it doesn't quite work as i want it to. The array I get after iterating over 3 files is just the last file. Somewhere along the way it seems to just overwrite the previous files. I'm not sure where though. Also I would like to remove rows with certain entries, but I'd be happy if the merging would work at least.
<?php
$dir = new DirectoryIterator("path1");
$destination = "path2";
$json = file_get_contents($destination);
$result = json_decode($json,true);
foreach ($dir as $fileinfo) {
if (!$fileinfo->isDot()) {
$path = $dir -> getPathname();
$data = file_get_contents($path);
echo $data; //works as intended. Prints 3 different Arrays after eachother
$current = json_decode(file_get_contents($path),true);
$result = array_merge($result,$current);
}
}
$final = json_encode($result);
file_put_contents($destination,$final);
?>
Thanks in advance for any help
The function array_merge has this overwriting behaviour, as specified in the manual:
If the input arrays have the same string keys, then the later value for that key will overwrite the previous one.
This effect can be illustrated with this little example:
$a1 = array("a" => 1, "b" => 2);
$a2 = array("a" => 100, "b" => 200);
$result = array_merge($a1, $a2);
print_r (json_encode($result));
output:
{"a":100,"b":200}
So, the values of the first array are lost.
There are several solutions, but it depends on which result you would like to get. If for instance you would like to get this:
{"a":[1, 100],"b":[2, 200]}
Then use the function array_merge_recursive instead of array_merge.
If you prefer to get this:
[{"a":1,"b":2},{"a":100,"b":200}]
Then use this code:
$result[] = $a1;
$result[] = $a2;
In your original code, that last solution would look like this:
$result[] = json_decode($json,true);
foreach ($dir as $fileinfo) {
// ...
$result[] = $current;
// ...
}

Divide randomly generated ids into equal groups

i'm using php and generating user's id like
$id = bin2hex(openssl_random_pseudo_bytes(16, $s));
And i would like to divide these ids into equals (or almost equals) groups. And in future i would like to know which group user belongs to.
Any ideas? What criteria can i choose for this?
I've found one variant of resolution. But maybe there is another, more pretty way...
$group = array_sum(str_split($id))%2;
OK this is a rough and ready answer; since the actual criteria you wish to sort on aren't given, I'm assuming the main goal is an even distribution of variables amongst your chosen container; I've used arrays here.
<?php
$id1 = 'abc';
$id2 = 'def';
$id3 = 'ghi';
$id4 = 'jk';
$id5 = 'lmn';
$id6 = 'opq';
$id7 = 'rst';
$id8 = 'uvx';
$id_array = array($id1, $id2, $id3, $id4, $id5, $id6, $id7, $id8);
$array1 = array();
$array2 = array();
$array3 = array();
$array4 = array();
$id_storage = array($array1, $array2, $array3, $array4);
$id_storage_size = sizeOf($id_storage);
foreach ($id_array as $indivId) {
$id_array_size = sizeOf($id_array);
$current_storage_array = $id_array_size % $id_storage_size;
$id_storage[$current_storage_array][] = $indivId;
array_shift($id_array);
}
//check them like so...
echo $id_storage[1][1];
?>
As for checking which array contains a given value:
<?php
$givenId = $id2;
foreach ($id_storage as $indiv_storage_array){
if (in_array($givenId, $indiv_storage_array)){
echo "Match found in $indiv_storage_array";
}
}
?>

Nested loops and array formation

Suppose that I start with an array that looks like:
$array_1 = array(array(1,2,3), array(2,4,5), array(3,6,7));
For simplicity, assume that I have a rule that says: delete the first subarray and then delete the first elements of the remaining subarrays. This would yield the result:
$new_array = array(array(4,5), array(6,7))
Then assume I expand the problem to larger arrays like:
$array_2 = array(array(1,2,3,4), array(2,3,4,5), array(3,4,5,6), array(4,5,6,7));
I have the same rule here - delete first subarray and then delete first elements of the remaining subarrays. BUT this rule must be continued until the smallest subarray contains only two elements (as in the first example). So that in stage one of the process, my new array would look like:
$new_array_s1 = array(array(3,4,5), array(4,5,6), array(5,6,7));
But in the final stage, the completed array would look like:
$new_array_s2 = array(array(5,6), array(6,7));
For context, here is my code for the $array_1 example:
<?php
$array_1 = array(array(1,2,3), array(2,4,5), array(3,6,7));
$array_shell = $array_1;
unset($array_shell[0]);
$array_size = count($array_shell);
$i = 0;
$cofactor = array();
while($i < $array_size) {
$el_part_[$i] = $array_1[$i];
unset($el_part_[$i][0]);
$el_part_[$i] = array_values($el_part_[$i]);
array_push($cofactor, $el_part_[$i]);
++$i;
}
echo '<pre>',print_r($cofactor,1),'</pre>';
?>
My Question: How can I generalise this code to work for N sized arrays?
You don't need a complicated code .. Just loop and use array_shift
Example:
print_r(cleanUp($array_1));
Function
function cleanUp($array) {
array_shift($array);
foreach($array as $k => $var) {
is_array($var) && array_shift($array[$k]);
}
return $array;
}
See Live DEMO
$num = count($array_1);
for($i=0;$i<=$num;$i++)
{
if($i==0)
unset($array_1[$i]);
else unset($array_1[$i][0]);
}
Building off of Baba's answer, to work with N element arrays (assuming each array contains the same number of elements):
<?php
$array_1 = array(array(1,2,3,4), array(2,4,5,6), array(3,6,7,8));
$array = $array_1;
while(count($array[0]) > 2)
$array = cleanUp($array);
print_r($array);
function cleanUp($array) {
array_shift($array);
foreach($array as $k => $var) {
is_array($var) && array_shift($array[$k]);
}
return $array;
}
This will keep reducing until the sub-arrays have only 2 elements.
-Ken

Change values in first key from 0 to count(array) - 1

Ok, I have an array like so:
$myArray[32]['value'] = 'value1';
$myArray[32]['type'] = 'type1';
$myArray[33]['value'] = 'value2';
$myArray[33]['type'] = 'type2';
$myArray[35]['value'] = 'value3';
$myArray[42]['value'] = 'value4';
$myArray[42]['type'] = 'type4';
Ok, looking for a quick way to change all numbers in the first key 32, 33, 35, and 42 into 0, 1, 2, and 3 instead. But I need to preserve the 2nd key and all of the values. The array is already ordered correctly, since I ordered it using a ksort, but now I need to reset the array from 0 - count($myArray) - 1 and keep the 2nd key intact and its value as well.
Can someone please help me?
$myArray = array_values($myArray);
There might be simpler solutions but here is one working solution:
$myArray = array();
$myArray[32]['value'] = 'value1';
$myArray[32]['type'] = 'type1';
$myArray[33]['value'] = 'value2';
$myArray[33]['type'] = 'type2';
$myArray[35]['value'] = 'value3';
$myArray[42]['value'] = 'value4';
$myArray[42]['type'] = 'type4';
$map = array_flip(array_keys($myArray)); // map old keys to new keys.
$newarray = array();
foreach($myArray as $key => $value) {
$newarray[$map[$key]] = $value; // use new key and old value.
}
You don't need it. Why not to just leave this array alone? Unnecessary moves would lead your code to a mess.

Categories