PHP - Combine multiple arrays with each other - php

I have been working on a tool that combines arrays containing attributes with each other.
The problem I'm having is that I don't know how to reach this goal.
I start by using the following code to decode the JSON to the arrays:
$input = '{"1":[["Red"],["Green"],["Blue"],["Purple"]],"2":[["S"],["M"],["L"]],"3":[["Wool"],["Cotton"]]}';
$arr = json_decode($input, true);
print_r($arr);
From that point, I don't know what to do. I have been trying to loop through arrays and, merging arrays but I can't find any way to reach my goal.
The following output in an array is my goal:
Red,S,Wool
Red,S,Cotton
Red,M,Wool
Red,M,Cotton
Red,L,Wool
Red,L,Cotton
Green,S,Wool
Green,S,Cotton
Green,M,Wool
Green,M,Cotton
Green,L,Wool
Green,L,Cotton
Blue,S,Wool
Blue,S,Cotton
Blue,M,Wool
Blue,M,Cotton
Blue,L,Wool
Blue,L,Cotton
Purple,S,Wool
Purple,S,Cotton
Purple,M,Wool
Purple,M,Cotton
Purple,L,Wool
Purple,L,Cotton
There is also a possibility that there will be instead of 3 like 4, 5, or more arrays with attributes.
I have found a tool which calculates this, but its unclear what the code behind the scenes does.https://www.dcode.fr/choices-combinations
Is there someone who can provide me with the code to solve this solution or link me to an existing question which shows how.

You can use a recursive function to create all the combinations of each different subarray. For example:
function combinations($array) {
if (count($array) == 1) return reset($array);
$result = array();
foreach (reset($array) as $value) {
foreach (combinations(array_slice($array, 1)) as $comb) {
$result[] = array_merge($value, $comb);
}
}
return $result;
}
$input = '{"1":[["Red"],["Green"],["Blue"],["Purple"]],"2":[["S"],["M"],["L"]],"3":[["Wool"],["Cotton"]]}';
$arr = json_decode($input, true);
$combs = combinations($arr);
This will return an array of arrays like this (based on your sample input data):
Array
(
[0] => Array
(
[0] => Red
[1] => S
[2] => Wool
)
[1] => Array
(
[0] => Red
[1] => S
[2] => Cotton
)
[2] => Array
(
[0] => Red
[1] => M
[2] => Wool
)
...
[22] => Array
(
[0] => Purple
[1] => L
[2] => Wool
)
[23] => Array
(
[0] => Purple
[1] => L
[2] => Cotton
)
)
To get a list of comma separated strings, you can then use array_map to apply implode to those arrays e.g.
$csv = array_map(function ($a) { return implode(',', $a); }, $combs);
This will give an array like this:
Array
(
[0] => Red,S,Wool
[1] => Red,S,Cotton
[2] => Red,M,Wool
[3] => Red,M,Cotton
[4] => Red,L,Wool
[5] => Red,L,Cotton
[6] => Green,S,Wool
[7] => Green,S,Cotton
[8] => Green,M,Wool
[9] => Green,M,Cotton
[10] => Green,L,Wool
[11] => Green,L,Cotton
[12] => Blue,S,Wool
[13] => Blue,S,Cotton
[14] => Blue,M,Wool
[15] => Blue,M,Cotton
[16] => Blue,L,Wool
[17] => Blue,L,Cotton
[18] => Purple,S,Wool
[19] => Purple,S,Cotton
[20] => Purple,M,Wool
[21] => Purple,M,Cotton
[22] => Purple,L,Wool
[23] => Purple,L,Cotton
)
Demo on 3v4l.org

Your input is currently putting all of the colours inside of an array and then inside another array. [["Red"],["Green"],["Blue"],["Purple"]]. Ideally you want them to be like ["Red", "Green", "Blue", "Purple"].
Aside from that you can loop over the elements turn them into the desired structure.
Once you have the structure for the colours, sizes and materials then you can loop over them and add them to a new array.
$input = '{"1":[["Red"],["Green"],["Blue"],["Purple"]],"2":[["S"],["M"],["L"]],"3":[["Wool"],["Cotton"]]}';
$arr = json_decode($input, true);
$test = [];
$sizes = [];
$colours = [];
$materials = [];
foreach($arr[1] as $key => $colour) {
$colours[] = $colour[0];
}
foreach($arr[2] as $key => $size) {
$sizes[] = $size[0];
}
foreach($arr[3] as $key => $material) {
$materials[] = $material[0];
}
foreach ($colours as $key => $colour) {
foreach($sizes as $key => $size) {
foreach ($materials as $key => $material) {
$test[] = $colour .','. $size . ','. $material;
}
}
}
print_r($test);
While ideally this isn't the most efficient it will achieve your desired output.
Demo here

Related

How do I add it all up by the `index` key in a PHP Array?

I am using PHP and I have an array
$nnarray = Array (
[9] => Array (
[1] => Array (
[2] => 433
[6] => 2
[4] => 101
)
[3] => Array (
[6] => 999
)
)
[14] => Array (
[2] => Array (
[2] => 0
[6] => 2
)
)
)
How do I add it all up by the index key? Output I would like as below
Array (
[9] => 1535
)
[14] => 2
)
)
1535 = 433+2+101+999 (All value under [9])
Now I using the following script to get the result, is it have another effective way?
foreach($nnarray as $key => $value){
foreach($nnarray[$key] as $nkey => $nvalue){
foreach($nnarray[$key][$nkey] as $nnkey => $nnvalue){
$newarray[$key] = $newarray[$key]+$nnvalue;
}
}
}
print_r($newarray);
You are confusing keys and values !
$newarray= array(); // create a new array to sum up
foreach ($array as $key1 => $valueArray1) { // looping through main array
$resultArray[$key1] = 0; // setting initial value to 0.
foreach ($valueArray1 as $key2 => $valueArray2) { // looping thru inner array
foreach ($valueArray2 as $key => $value) { // looping thru innermost array
$newarray[$key1] += $value;
}
}
}
var_dump($newarray);
And the result will be
array(2) {
[9]=>
int(1535)
[14]=>
int(2)
}
Shorter version, requires >= PHP7.4.0
map sum => map sum
$result = array_map(fn($v) => array_sum(array_map(fn($v) => array_sum($v), $v)), $data);
Result:
Array
(
[9] => 1535
[14] => 2
)
https://3v4l.org/04WcF
A few exotic options.
Iterators:
$result = array_map(function($val)
{
return array_sum(iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveArrayIterator($val))));
}, $array);
Array walking:
$result = array_map(function($val)
{
array_walk_recursive($val, function($v) use (&$sum) { $sum += $v; });
return $sum;
}, $array);

How can I extract values from an array (array_values isn't working)?

I have the following PHP array
[1] => Array
(
[0] => 9780881220766
[1] => 0881220760
)
[2] => Array
(
[0] => 9780141374284
[1] => 0141374284
)
[3] => Array
(
[0] => 057305133X
[1] => 9780573051333
))
I would like the output to be as follows:
[0] => 9780881220766
[1] => 0881220760
[2] => 9780141374284
[3] => 0141374284
[4] => 057305133X
[5] => 9780573051333
I tried using array_values but I'm not getting any output.
I also tried to extract the values using a foreach loop:
foreach ($rawIsbns as $isbnKey => $isbnValue){
$formattedIsbns[] = $isbnValue;
}
However, I'm not managing.
$a = array();
foreach ($array as $tmp) {
if (is_array($tmp)) $a = array_merge($a, $tmp);
}
Created this function that allows you to merge 1 or more arrays together into the format you asked for:
function sortarr(...$arr){
$tmparr = [];
foreach($arr as $aa) foreach($aa as $a) $tmparr = array_merge($tmparr, $a);
return $tmparr;
}
Example Usage:
<?php
# First array provided
$array = array(
[
"9780881220766",
"0881220760"
],
[
"9780141374284",
"0141374284"
],
[
"057305133X",
"9780573051333"
]
);
# Second array just to show how you can input more than 1 array into the function
$array2 = array(
[
"6234808972234",
"67834757"
],
[
"0287568924344234",
"234690543"
],
[
"34565786978099x",
"3569876546"
]
);
function sortarr(...$arr){
# Declare our temp array
$tmparr = [];
# Iterates through each of the arrays inside the array(s) provided
foreach($arr as $aa) foreach($aa as $a) $tmparr = array_merge($tmparr, $a);
# Return the results
return $tmparr;
}
print_r( sortarr($array, $array2) );
Results:
Array
(
[0] => 9780881220766
[1] => 0881220760
[2] => 9780141374284
[3] => 0141374284
[4] => 057305133X
[5] => 9780573051333
[6] => 6234808972234
[7] => 67834757
[8] => 0287568924344234
[9] => 234690543
[10] => 34565786978099X
[11] => 3569876546
)
Live Demo: http://sandbox.onlinephpfunctions.com/code/838a108498f446ae4a5f8e42fa441ec11941c567
I managed to solve the problem by initializing an array and adding values of subsequent nested arrays using array_push
function isbns($rawIsbns) {
$prevArrayValues = null;
foreach ($rawIsbns as $value) {
if (!isset($prevArrayValues)) {
$prevArrayValues = []; //initiallise first value unless initialized
}
if (empty($value)) {
$return = []; //disregard empty values
} else {
$return = $value; // add arrays to existing array
}
$prevArrayValues = array_merge($prevArrayValues, $return);
}
return $prevArrayValues;
}

php - rearranging an array into groups

I have an array of filenames:
Array
(
[2] => 1_1_page2-img1.jpg
[3] => 1_2_page2-img1-big.jpg
[4] => 2_1_page2-img1.jpg
[5] => 2_2_page2-img1-big.jpg
[6] => 3_1_page2-img1.jpg
[7] => 4_1_page2-img1.jpg
[8] => 4_2_page2-img1.jpg
[9] => 5_2_page2-img1.jpg
)
I'm trying to rearrange them so they're grouped together by their first number. I'm guessing I could maybe separate them with a pipe so I could then distinguish them afterwards. Either that or a multidimensional array.
I know I can perform an explode("_",$filename); to get the first and second digits before the underscores.
The catch is even though the beginning numbers should always increment, there won't necessarily be 2 files per initial number.
So I'm either trying to make it into the following:
Array
(
[0] => 1_1_page2-img1.jpg|1_2_page2-img1-big.jpg
[1] => 2_1_page2-img1.jpg|2_2_page2-img1-big.jpg
[2] => 3_1_page2-img1.jpg|
[3] => 4_1_page2-img1.jpg|4_2_page2-img1.jpg
[4] => |5_2_page2-img1.jpg
)
Or something a bit tidier perhaps? I just can't work out the foreach to put them together.
Or is there an array related command that will put them together easier?
My preference would be to store them in subarrays, as this will be much easier to deal with in the long run; so this would be a possibility, given your array is in $arr:
$newarr = array ();
while (list($key, $val) = each($arr)) {
$subarray_index = substr($val, 0, strpos($val, "_"));
$newarr[$subarray_index][] = $val;
}
Is this what you mean?
$arr = Array(
2 => '1_1_page2-img1.jpg',
3 => '1_2_page2-img1-big.jpg',
4 => '2_1_page2-img1.jpg',
5 => '2_2_page2-img1-big.jpg',
6 => '3_1_page2-img1.jpg',
7 => '4_1_page2-img1.jpg',
8 => '4_2_page2-img1.jpg',
9 => '5_2_page2-img1.jpg'
);
function orderArray($pArr){
$first = '0';
$newArr = array();
foreach($pArr as $val){
if(strpos($val,$first) !== 0){
if(substr($val,2,1)==='1'){
$newArr[]=$val;
}else{
$newArr[]='|'.$val;
}
$first = substr($val,0,1);
}else{
$curIndex = count($newArr) - 1;
$newArr[$curIndex] = $newArr[$curIndex].'|'.$val;
}
return $newArr;
}
$result = orderArray($arr);
print "number of values: ".count($result)."<br>";
foreach($result as $value){
print $value."<br>";
}
Just worked it out now based on another post in stackoverflow:
foreach ($scanned_directory as $filename){
$ids = explode("_",$filename);
$groups[$ids[0]][] = $filename;
}
echo "<pre>";
ksort($groups);
print_r($groups);
echo "</pre>";
Displays:
Array
(
[1] => Array
(
[0] => 1_1_page2-img1.jpg
[1] => 1_2_page2-img1-big.jpg
)
[2] => Array
(
[0] => 2_1_page2-img1.jpg
[1] => 2_2_page2-img1-big.jpg
)
[3] => Array
(
[0] => 3_1_page2-img1.jpg
[1] => 3_2_page2-img1-big.jpg
)
[10] => Array
(
[0] => 10_1_page2-img1.jpg
)
[11] => Array
(
[0] => 11_2_page2-img1-big.jpg
)
)
There isn't a nice automated way of doing this, but you could use a simple loop:
$array = [];
foreach ($filename as $file) {
$fields = explode('_', $file);
$array[$fields[0]][$fields[1]] = $file;
}
An example is located here.

PHP Group array by values

I have an array like this:
Array (
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
[4] => ing_2_ing
[5] => ing_2_amount
[6] => ing_2_det
[7] => ing_2_meas
)
And I want to group the values into an array like this:
Array (
[0] => Array(
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
)
[1] => Array(
[0] => ing_2_ing
[1] => ing_2_amount
[2] => ing_2_det
[3] => ing_2_meas
)
)
There may be many other items named like that: ing_NUMBER_type
How do I group the first array to the way I want it? I tried this, but for some reason, strpos() sometimes fails:
$i = 1;
foreach ($firstArray as $t) {
if (strpos($t, (string)$i)) {
$secondArray[--$i][] = $t;
} else {
$i++;
}
}
What is wrong? Can you advice?
It depends what you are trying to achieve, if you want to split array by chunks use array_chunk method and if you are trying to create multidimensional array based on number you can use sscanf method in your loop to parse values:
$result = array();
foreach ($firstArray as $value)
{
$n = sscanf($value, 'ing_%d_%s', $id, $string);
if ($n > 1)
{
$result[$id][] = $value;
}
}
<?php
$ary1 = array("ing_1_ing","ing_1_amount","ing_1_det","ing_1_meas","ing_2_ing","ing_2_amount","ing_2_det","ing_2_meas");
foreach($ary1 as $val)
{
$parts = explode("_",$val);
$ary2[$parts[1]][]=$val;
}
?>
This creates:
Array
(
[1] => Array
(
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
)
[2] => Array
(
[0] => ing_2_ing
[1] => ing_2_amount
[2] => ing_2_det
[3] => ing_2_meas
)
)
What I'd do is something like this:
$result = array();
foreach ($firstArray as $value)
{
preg_match('/^ing_(\d+)_/', $value, $matches);
$number = $matches[1];
if (!array_key_exists($number, $result))
$result[$number] = array();
$result[$number][] = $value;
}
Basically you iterate through your first array, see what number is there, and put it in the right location in your final array.
EDIT. If you know you'll always have the numbers start from 1, you can replace $number = $matches[1]; for $number = $matches[1] - 1;, this way you'll get exactly the same result you posted as your example.

How can I create multidimensional arrays from a string in PHP?

So My problem is:
I want to create nested array from string as reference.
My String is "res[0]['links'][0]"
So I want to create array $res['0']['links']['0']
I tried:
$result = "res[0]['links'][0]";
$$result = array("id"=>'1',"class"=>'3');
$result = "res[0]['links'][1]";
$$result = array("id"=>'3',"class"=>'9');
when print_r($res)
I see:
<b>Notice</b>: Undefined variable: res in <b>/home/fanbase/domains/fanbase.sportbase.pl/public_html/index.php</b> on line <b>45</b>
I need to see:
Array
(
[0] => Array
(
[links] => Array
(
[0] => Array
(
[id] => 1
[class] => 3
)
)
)
[1] => Array
(
[links] => Array
(
[0] => Array
(
[id] => 3
[class] => 9
)
)
)
)
Thanks for any help.
So you have a description of an array structure, and something to fill it with. That's doable with something like:
function array_create(&$target, $desc, $fill) {
preg_match_all("/[^\[\]']+/", $desc, $uu);
// unoptimized, always uses strings
foreach ($uu[0] as $sub) {
if (! isset($target[$sub])) {
$target[$sub] = array();
}
$target = & $target[$sub];
}
$target = $fill;
}
array_create( $res, "[0]['links'][0]", array("id"=>'1',"class"=>'3') );
array_create( $res, "[0]['links'][1]", array("id"=>'3',"class"=>'9') );
Note how the array name itself is not part of the structure descriptor. But you could theoretically keep it. Instead call the array_create() function with a $tmp variable, and afterwards extract() it to achieve the desired effect:
array_create($tmp, "res[0][links][0]", array(1,2,3,4,5));
extract($tmp);
Another lazy solution would be to use str_parse after a loop combining the array description with the data array as URL-encoded string.
I have a very stupid way for this, you can try this :-)
Suppose your string is "res[0]['links'][0]" first append $ in this and then put in eval command and it will really rock you. Follow the following example
$tmp = '$'.'res[0]['links'][0]'.'= array()';
eval($tmp);
Now you can use your array $res
100% work around and :-)
`
$res = array();
$res[0]['links'][0] = array("id"=>'1',"class"=>'3');
$res[0]['links'][0] = array("id"=>'3',"class"=>'9');
print_r($res);
but read the comments first and learn about arrays first.
In addition to mario's answer, I used another function from php.net comments, together, to make input array (output from jquery form serializeArray) like this:
[2] => Array
(
[name] => apple[color]
[value] => red
)
[3] => Array
(
[name] => appleSeeds[27][genome]
[value] => 201
)
[4] => Array
(
[name] => appleSeeds[27][age]
[value] => 2 weeks
)
[5] => Array
(
[name] => apple[age]
[value] => 3 weeks
)
[6] => Array
(
[name] => appleSeeds[29][genome]
[value] => 103
)
[7] => Array
(
[name] => appleSeeds[29][age]
[value] => 2.2 weeks
)
into
Array
(
[apple] => Array
(
[color] => red
[age] => 3 weeks
)
[appleSeeds] => Array
(
[27] => Array
(
[genome] => 201
[age] => 2 weeks
)
[29] => Array
(
[genome] => 103
[age] => 2.2 weeks
)
)
)
This allowed to maintain numeric keys, without incremental appending of array_merge. So, I used sequence like this:
function MergeArrays($Arr1, $Arr2) {
foreach($Arr2 as $key => $Value) {
if(array_key_exists($key, $Arr1) && is_array($Value)) {
$Arr1[$key] = MergeArrays($Arr1[$key], $Arr2[$key]);
}
else { $Arr1[$key] = $Value; }
}
return $Arr1;
}
function array_create(&$target, $desc, $fill) {
preg_match_all("/[^\[\]']+/", $desc, $uu);
foreach ($uu[0] as $sub) {
if (! isset($target[$sub])) {
$target[$sub] = array();
}
$target = & $target[$sub];
}
$target = $fill;
}
$input = $_POST['formData'];
$result = array();
foreach ($input as $k => $v) {
$sub = array();
array_create($sub, $v['name'], $v['value']);
$result = MergeArrays($result, $sub);
}

Categories