Related
This question already has answers here:
Transposing multidimensional arrays in PHP
(12 answers)
Closed 4 months ago.
Is there an efficient way to change the structure of this multidimensional array? I want to group the column values.
//$arrayBefore
[[5, 4, 10], [11, 13, 15], [32, 14, 15]];
Desired result:
//$arrayAfter
[[5, 11, 32], [4, 13, 14], [10, 15, 15]];
<?php
$array = [[5, 4, 10], [11, 13, 15], [32, 14, 15]];
for($i = 0; $i < count($array); $i++) {
for ($j = 0; $j < count($array[$i]); $j++) {
$temp[$j][] = $array[$i][$j];
}
}
print_r($temp);
OUTPUT: http://www.phpwin.org/s/BVxAx3
You can do it based on array_column():-
<?php
$array = [[5, 4, 10], [11, 13, 15], [32, 14, 15]];
$final_array = [array_column($array,0),array_column($array,1),array_column($array,2)];
print_r($final_array );
Output:-https://eval.in/836310
Note:- above code will work only for this array.
More general and considering all aspects code is using foreach():-
<?php
$array = [[5, 4, 10], [11, 13, 15], [32, 14, 15]];
$final_array = array();
foreach($array as $arr){
foreach($arr as $key=>$value){
$final_array[$key][]=$value;
}
}
print_r($final_array);
Output:- https://eval.in/836313
If you're unsure of the array structure, you can also use foreach. Will work for more than 3 in each arrays with out any code modification
<?
$arr = [[5, 4, 10], [11, 13, 15], [32, 14, 15]];
foreach($arr as $value_arr){
$i=0;
foreach($value_arr as $value){
if ($value){
$arr2[$i][]=$value;
$i++;
}
}
}
echo "<pre>";
print_r($arr2);
echo "</pre>";
?>
Array
(
[0] => Array
(
[0] => 5
[1] => 11
[2] => 32
)
[1] => Array
(
[0] => 4
[1] => 13
[2] => 14
)
[2] => Array
(
[0] => 10
[1] => 15
[2] => 15
)
)
I've already been mocked on SO for promoting a variadic approach for this kind of question, but I think it is important to show what the clever developers of php have afforded coders to do.
The ... (splat operator) tells array_map() that a multi-dimensional (with a potentially variable number of subarrays) array is coming. The function then synchronously iterates each individual subarray.
In the following code, I have commented out a method that statically names the arguments $v1,$v2,$v3 used by array_map(). This will work for the OP's case.
The line of code following the commented one, is a method that dynamically accesses the values without needing to do any variable naming. This will also be hugely flexible for any case where the structure of the multi-dimensional array changes its size/shape.
PHP Manual references:
variadic functions
func_get_args()
One-liner (requires PHP5.6+): (Demo with additional examples/considerations)
$m_array=[[5, 4, 10], [11, 13, 15], [32, 14, 15]];
//$new=array_map(function($v1,$v2,$v3){return [$v1,$v2,$v3];},...$m_array);
$new=array_map(function(){return func_get_args();},...$m_array);
var_export($new);
Output:
array (
0 =>
array (
0 => 5,
1 => 11,
2 => 32,
),
1 =>
array (
0 => 4,
1 => 13,
2 => 14,
),
2 =>
array (
0 => 10,
1 => 15,
2 => 15,
),
)
I have a multidimensional array. I need to check if any value in this array has contain same value. If, then execute. What is the better way to check this, or the simplest way TIA
$array[] = array(5, 10, 15, 20, 25, 30);
$array[] = array(1, 2, 3, 4, 5, 6);
$array[] = array(2, 6, 8, 10, 12, 14);
Array
(
[0] => Array
(
[0] => 5
[1] => 10
[2] => 15
[3] => 20
[4] => 25
[5] => 30
)
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
)
[2] => Array
(
[0] => 2
[1] => 6
[2] => 8
[3] => 10
[4] => 12
[5] => 14
)
)
If I understood your question correctly, you are looking for a way of finding values that appears in more than one of the inner arrays..? Here are two solutions for that, using some built-in PHP array methods.
Setup
Flatten $array (initial step for both methods) using array_merge on itself
Code:
$array[] = array(5, 10, 15, 20, 25, 30);
$array[] = array(1, 2, 3, 4, 5, 6);
$array[] = array(2, 6, 8, 10, 12, 14, 5);
// 5, 10, 15, 20, 25, 30, 1, 2, 3, 4, 5, 6, 2, 6, 8, 10, 12, 14, 5
$array = call_user_func_array('array_merge', $array);
Method A
Get an array of unique values in $array (duplicates removed)
Get what was removed (= the duplicates) by comparing that array to the original $array
Make sure values appear only once in the final array
Code:
$duplicates =
array_unique(
array_diff_key(
$array,
array_unique($array)
)
);
// $duplicates = 5, 2, 6, 10
Method B
Get a list of how many times each value appears in $array
Filter that list keeping only values that appears more than once (= duplicates)
Get the keys of that list (the actual $array values)
Code:
$duplicates =
array_keys(
array_filter(
array_count_values($array),
function ($count) {
return $count > 1;
}
)
);
// $duplicates = 5, 10, 2, 6
Just loop through the array and subarray filling $isRepeated with values and frequencies of appearance. When $isRepeated[certain_value] exists means this value was found before:
$array[] = array(5, 10, 15, 20, 25, 30);
$array[] = array(1, 2, 3, 4, 5, 6);
$array[] = array(2, 6, 8, 10, 12, 14);
$isRepeated = array();
foreach($array as $subArray) {
foreach($subArray as $item) {
if (!isset($isRepeated[$item])) {
$isRepeated[$item] = 0;
} else {
$isRepeated[$item]++;
echo "\n<br>Item $item is repeated";
}
}
}
http://ideone.com/9yObII
Output:
Item 5 is repeated
Item 2 is repeated
Item 6 is repeated
Item 10 is repeated
This question already has answers here:
How to Sum Columns of a Multi-Dimensional Array?
(4 answers)
Closed 5 months ago.
I have an arrays with dynamic name. My array could be more than 3, depends and array variable should be unique
$loopThrice = 3;
$getSum = 0;
$total = array();
$array0 = array(5, 10, 15, 20, 25, 30);
$array1 = array(1, 2, 3, 4, 5, 6);
$array2 = array(2, 6, 8, 10, 12, 14);
for($a=0; $a < $loopThrice; $a++){ // loop 3x to get unique array name
foreach (${'array'.$a} as $key => $value) { // $array0, $array1, $array2,
//Right here is my problem, I'm not sure if this the correct way to get the sum of $array0,1,2
//get the sum of array0,1,2 -- newarray(8, 18, 26, 34, 42, 50)
$getSum +=
//store newarray
array_push($total, $getSum);
}
}
I need to get an output like this:
Array (
[0] => 8
[1] => 18
[2] => 26
[3] => 34
[4] => 43
[5] => 50
)
Why aren't you using a multidimensional array?
$array = array(); // hungarian notation
$array[] = array(5, 10, 15, 20, 25, 30);
$array[] = array(1, 2, 3, 4, 5, 6);
$array[] = array(2, 6, 8, 10, 12, 14);
In this case you will have an array of arrays:
Array
(
[0] => Array
(
[0] => 5
[1] => 10
[2] => 15
[3] => 20
[4] => 25
[5] => 30
)
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
)
[2] => Array
(
[0] => 2
[1] => 6
[2] => 8
[3] => 10
[4] => 12
[5] => 14
)
)
You can go with nested for loops:
$sumArray = array();
$arrayCount = count($array);
$elementCount = 0;
foreach($array as $subarray)
{
$count = count($subarray);
$elementCount = $elementCount < $count ? $count : $elementCount;
}
for($i = 0; $i < $elementCount; $i++)
{
$sumArray[$i] = 0;
for($j = 0; $j < $arrayCount; $j++)
{
$sumArray[$i] += $array[$j][$i];
}
}
print_r($sumArray);
The output is
Array
(
[0] => 8
[1] => 18
[2] => 26
[3] => 34
[4] => 42
[5] => 50
)
Now, if you have a disproportioned sub-arrays (i.e. different count of elements in each sub-array), you will still get some sort of result, as missing elements will be assumed to be 0. So, with the input of:
$array = array(); // hungarian notation
$array[] = array(5, 10, 15, 20, 25);
$array[] = array(1, 2, 3, 4, 5, 6);
$array[] = array(2, 6, 8, 10);
You will still get the result:
Array
(
[0] => 8
[1] => 18
[2] => 26
[3] => 34
[4] => 30
[5] => 6
)
Well the multi array is the way to go, but you can still do it this way:
$loopThrice = 3;
$getSum = 0;
$total = array();
$array0 = array(5, 10, 15, 20, 25, 30);
$array1 = array(1, 2, 3, 4, 5, 6);
$array2 = array(2, 6, 8, 10, 12, 14);
// find which arrray has the most values
for($a=0; $a < $loopThrice; $a++){
$max_index = (count(${'array'.$a}) > $max_index ? count(${'array'.$a}) : $max_index);
}
for($i=0; $i < $max_index; $i++){
for($a=0; $a < $loopThrice; $a++){
$total[$i] += ${'array'.$a}[$i];
}
}
print_r($total);
// prints Array ( [0] => 8 [1] => 18 [2] => 26 [3] => 34 [4] => 42 [5] => 50 )
This should work for you:
$array0 = array(5, 10, 15, 20, 25, 30);
$array1 = array(1, 2, 3, 4, 5, 6);
$array2 = array(2, 6, 8, 10, 12, 14);
$var_prefix = 'array';
$arr_count = 0;
$max_fields = 0;
while(isset(${$var_prefix.$arr_count})) {
$data[] = ${$var_prefix.$arr_count};
if(count(${$var_prefix.$arr_count})>$max_fields) {
$max_fields = count(${$var_prefix.$arr_count});
};
$arr_count++;
}
for($i=0; $i<$max_fields; $i++) {
$result[$i] = array_sum(array_column($data, $i));
}
echo '<pre>';
print_r($result);
echo '</pre>';
die();
I don't know why you have individual array variables, but the process remains the same as if you declare a single array containing those arrays as rows in a multi-dimensional array.
Once you have a multi-dimensional array, the spread operator (...) will feed columns of data into array_map()'s custom function body -- where array_sum() can be called upon.
This task is effectively summing transposed data.
Code: (Demo)
var_export(
array_map(fn() => array_sum(func_get_args()), $array0, $array1, $array2)
);
Or:
var_export(
array_map(fn(...$cols) => array_sum($cols), $array0, $array1, $array2)
);
Output (from either approach):
array (
0 => 8,
1 => 18,
2 => 26,
3 => 34,
4 => 42,
5 => 50,
)
Ok, im having troubles figuring out why my str_split is giving strange array output, this is the code:
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, 20, 23, "string3"),
4 => array(44, 55, 66, 77)
);
$newArray = array();
$keys = array_keys($test);
for($i=0; $i < count($test); $i++){
foreach($test[$keys[$i]] as $key => $value){
}
$output = str_split($key);
echo "<pre>";
print_r($output);
echo "</pre>";
Array output is:
Array
(
[0] => 3
)
Array
(
[0] => 3
)
Array
(
[0] => 3
)
Array
(
[0] => 4
)
Array
(
[0] => 3
)
And im expecting output like this:
Array ([0] => 3
[1] => 3
[2] => 3
[3] => 4
[4] => 3
)
Im wondering why is this happening? Thank you.
To achieve the output given, you would just do:
<?php
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, 20, 23, "string3"),
4 => array(44, 55, 66, 77)
);
foreach ($test as $row) {
$output[] = count($row)-1; // non-associative, so the last key is
} // just the length of the array minus 1
print_r($output);
?>
as the sub-arrays are not associative.
If they are, replace the line inside the loop with:
$keys = array_keys($row); // get the keys of the row
$output[] = $keys[count($keys)-1]; // and access the last of them
with your code the solution is, but it is not an efficient way of doing it.
<?php
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, 20, 23, "string3"),
4 => array(44, 55, 66, 77)
);
$newArray = array();
$keys = array_keys($test);
for($i=0; $i < count($test); $i++){
foreach($test[$i] as $key => $value){
$output[$i] = str_split($key)[0];
}
echo "<pre>";
//print_r($output);
echo "</pre>";
}
var_dump($output);
output
array (size=5)
0 => string '3' (length=1)
1 => string '3' (length=1)
2 => string '3' (length=1)
3 => string '4' (length=1)
4 => string '3' (length=1)
But by changing it to this will work, for arrays when the string position is not constant .
<?php
$test = array(0 => array(53, 22, 12, "string"),
1 => array(94, 84, 94, "string1"),
2 => array(56, 45, 104, "string2"),
3 => array(33, 21, "string3", 20, 23),
4 => array(44, 55, 66, 77)
);
$newArray = array();
$keys = array_keys($test);
for($i=0; $i < count($test); $i++){
foreach($test[$i] as $key => $value){
if(is_string($value)){
unset($test[$i][$key]);
}
$output[$i] = count($test[$i]);
}
echo "<pre>";
//print_r($output);
echo "</pre>";
}
var_dump($output);
output
array (size=5)
0 => int 3
1 => int 3
2 => int 3
3 => int 4
4 => int 4
I want get the keys of continuous values of an array.
For example:
how to change this array:
array(
2 => 11,
3 => 11,
4 => 11,
6 => 12,
7 => 13,
8 => 13,
10 => 11,
11 => 11,
12 => 14
)
to this one:
array(
array(2, 3, 4),
array(6),
array(7, 8),
array(10, 11),
array(12)
)
Thx in advance!
Edited Code.
<?php
$arr = [2 => 11, 3 => 11,4 => 11, 6 => 12, 7 => 13, 8 => 13, 10 => 11, 11 => 11,12 => 14];
$newArr = [];
$lastVal = null;
$currArr = [];
foreach($arr AS $key=>$value){
if($lastVal == $value){
$curArr[] = $key;
}else{
if($lastVal != null){
$newArr[] = $curArr;
}
$lastVal = $value;
$curArr = [$key];
}
}
$newArr[] = $curArr;
I'm sure there's a more elegant way.
$data = array(
2 => 11,
3 => 11,
4 => 11,
6 => 12,
7 => 13,
8 => 13,
10 => 11,
11 => 11,
12 => 14
);
$result = array();
array_walk(
$data,
function ($value, $key) use (&$result){
static $v;
if ($value == $v) {
$result[max(array_keys($result))][] = $key;
} else {
$result[] = array($key);
}
$v = $value;
}
);
var_dump($result);