Merging two foreach in php laravel/api - php

Good day! i had success in finding answers that shortens my code. Someone said that i can merge the foreach statements for it to become even shorter. but i searched everywhere but cant seem to find any solution with similar codes that i have. I just want to know how can i merge the two foreach.
here is my code:
$newArray = [];
$keys = ['name', 'sex', 'age', 'height', 'weight'];
foreach(explode(PHP_EOL, Storage::get('upload/test.txt')) as $key => $line) {
$finalArray = [];
foreach( explode(',', $line) as $i => $value){
$finalArray[ $keys [ $i ] ] = $value;
}
array_push($newArray, $finalArray);
}
die(json_encode($newArray));
here is another code with the same output as the first code:
$newArray = array();
foreach(explode(PHP_EOL, Storage::get('upload/test.txt')) as $key => $line) {
array_push($newArray, explode(',', $line));
}
$finalArray = array();
foreach($newArray as $key) {
$key = [
"name" => $key[0],
"sex" => $key[1],
"age" => $key[2],
"height" => $key[3],
"weight" => $key[4],
];
array_push($finalArray, $key);
}
die(json_encode($finalArray));

You could make it simpler by using array_combine:
$newArray = [];
$keys = ['name', 'sex', 'age', 'height', 'weight'];
foreach (explode(PHP_EOL, Storage::get('upload/test.txt')) as $line) {
$newArray[] = array_combine($keys, explode(',', $line));
}
Or you could use array_map() and do something like:
$keys = ['name', 'sex', 'age', 'height', 'weight'];
$newArray = array_map(function ($line) use ($keys) {
return array_combine($keys, explode(',', $line));
}, explode(PHP_EOL, Storage::get('upload/test.txt')));

Related

Combine array and add key for each array

I just can't find the right question for this
pretty much merging array From this
$arr1 = ["temp1", "temp2", "temp3"];
$arr2 = [5, 7, 2];
to this
$combined = [["name" => "temp1", "number" => 5], ["name" => "temp2", "number" => 7], ["name" => "temp3", "number" => 2]];
any idea to do it in most efficient way other than foreach?
$arr1 = ["temp1", "temp2", "temp3"];
$arr2 = [5, 7, 2];
foreach($arr1 as $key => $value)
{
$r[$key]['name'] = $value;
$r[$key]['number'] = $arr2[$key];
}
print_r($r);
Built-in function array_map actually can work with multiple arrays:
$result = array_map(function($value1, $value2) {
return ["name" => $value1, "number" => $value2];
}, $arr1, $arr2);
Here are some benchmarks comparing with simple foreach
You can use a foreach loop,
$result = [];
foreach($arr1 as $key => $value){
$resutl[] = array("name"=>$value,"number"=>$arr2[$key]);
}
You can do the following code to get your result
$arr1 = ["temp1", "temp2", "temp3"];
$arr2 = [5, 7, 2];
$count = count($arr1);
$combined = array();
for($i=0;$i<$count;$i++){
$combined[$i]['name'] = $arr1[$i];
$combined[$i]['number'] = $arr2[$i];
}

How to implode subarrays in a 2-dimensional array?

I want to implode values in to a comma-separated string if they are an array:
I have the following array:
$my_array = [
"keywords" => "test",
"locationId" => [ 0 => "1", 1 => "2"],
"industries" => "1"
];
To achieve this I have the following code:
foreach ($my_array as &$value)
is_array($value) ? $value = implode(",", $value) : $value;
unset($value);
The above will also change the original array. Is there a more elegant way to create a new array that does the same as the above?
I mean, implode values if they are an array in a single line of code? perhaps array_map()? ...but then I would have to create another function.
Just create a new array and set the elements (-;
<?php
...
$new_array = [];
foreach ($my_array as $key => $value)
$new_array[$key] = is_array($value) ? implode(",", $value) : $value;
Just append values to new array:
$my_array = [
"keywords" => "test",
"locationId" => [ 0 => "1", 1 => "2"],
"industries" => "1",
];
$new_Array = [];
foreach ($my_array as $value) {
$new_Array[] = is_array($value) ? implode(",", $value) : $value;
}
print_r($new_Array);
And something that can be called a "one-liner"
$new_Array = array_reduce($my_array, function($t, $v) { $t[] = is_array($v) ? implode(",", $v) : $v; return $t; }, []);
Now compare both solutions and tell which is more readable.
You don't need to write/iterate a conditional statement if you type the strings (non-arrays) as single-element arrays before imploding them.
With array_map(): (Demo)
$my_array = [
"keywords" => "test",
"locationId" => [ 0 => "1", 1 => "2"],
"industries" => "1"
];
var_export(
array_map(
function($v) {
return implode(',', (array)$v);
},
$my_array
)
);
Or from PHP7.4, array_map() with arrow function syntax: (Demo)
var_export(
array_map(fn($v) => implode(',', (array)$v), $my_array)
);
Or array_walk() and modification by reference (Demo)
array_walk(
$my_array,
function(&$v) {
$v = implode(',', (array)$v);
}
);
var_export($my_array);
Or a foreach loop: (Demo)
foreach ($my_array as &$v) {
$v = implode(',', (array)$v);
}
var_export($my_array);
All snippets will output:
array (
'keywords' => 'test',
'locationId' => '1,2',
'industries' => '1',
)
$arr = array( 'key1' => array( 'one', 'key2' => array( 'two',
'three' ) ), 'four', 'five' );
$finalData = [];
array_walk_recursive(
$arr,
function( $subArr ) use ( &$finalData ) {
$finalData[] = $subArr;
}
);
$str = is_array( $finalData ) ? implode( ",", $finalData ) : $finalData;
print_r( $str ); // one,two,three,four,five

How to convert PHP array

I have an array like this one:
array( array("key1" => "value1"), array("key2" => "value2"), ... )
I need to convert it to this format:
array( "value1", "value2", ... )
How can I do it using PHP?
Looping would be acceptable in this case. If you do want an example without looping, you can use array_map but I don't think it would be more "clear and simple":
$array = array_map(function($value) {
return reset($value);
}, $array);
This function SHOULD (untested) return a single array with no associative keys from your mufti-dimentional array.
function single_array ($array) {
$array2 = array();
if (is_array($array)) {
foreach ($array as $key => $val) {
if (is_array($val)) {
$array2[] = single_array($val);
}else{
$array2[] = $val;
}
}
}
return $array2;
}
$array = single_array($array);

PHP array manipulation

I have an array as $arr = array("name" => "Fom Xong" , "Sales" => "100");
From this array I want to generate a string something like this
$str = 'name="Fom Xon" Sales="100"';
Is it possible???
thanks in advance
For example you can do like this:
$tmp_arr = array();
foreach ($arr as $key => $val)
$tmp_arr[] = $key.'="'.$val.'"';
$str = implode(' ', $tmp_arr);
$output = array();
foreach ($arr as $key => $value) {
$output[] = "$key=\"$value\"";
}
echo join(' ', $output);
Or:
echo join(' ', array_map(function ($key, $value) { return "$key=\"$value\""; }, array_keys($arr), $arr));

Transposing multidimensional arrays in PHP

How would you flip 90 degrees (transpose) a multidimensional array in PHP? For example:
// Start with this array
$foo = array(
'a' => array(
1 => 'a1',
2 => 'a2',
3 => 'a3'
),
'b' => array(
1 => 'b1',
2 => 'b2',
3 => 'b3'
),
'c' => array(
1 => 'c1',
2 => 'c2',
3 => 'c3'
)
);
$bar = flipDiagonally($foo); // Mystery function
var_dump($bar[2]);
// Desired output:
array(3) {
["a"]=>
string(2) "a2"
["b"]=>
string(2) "b2"
["c"]=>
string(2) "c2"
}
How would you implement flipDiagonally()?
Edit: this is not homework. I just want to see if any SOers have a more creative solution than the most obvious route. But since a few people have complained about this problem being too easy, what about a more general solution that works with an nth dimension array?
i.e. How would you write a function so that:
$foo[j][k][...][x][y][z] = $bar[z][k][...][x][y][j]
?(ps. I don't think 12 nested for loops is the best solution in this case.)
function transpose($array) {
array_unshift($array, null);
return call_user_func_array('array_map', $array);
}
Or if you're using PHP 5.6 or later:
function transpose($array) {
return array_map(null, ...$array);
}
With 2 loops.
function flipDiagonally($arr) {
$out = array();
foreach ($arr as $key => $subarr) {
foreach ($subarr as $subkey => $subvalue) {
$out[$subkey][$key] = $subvalue;
}
}
return $out;
}
I think you're referring to the array transpose (columns become rows, rows become columns).
Here is a function that does it for you (source):
function array_transpose($array, $selectKey = false) {
if (!is_array($array)) return false;
$return = array();
foreach($array as $key => $value) {
if (!is_array($value)) return $array;
if ($selectKey) {
if (isset($value[$selectKey])) $return[] = $value[$selectKey];
} else {
foreach ($value as $key2 => $value2) {
$return[$key2][$key] = $value2;
}
}
}
return $return;
}
Transposing an N-dimensional array:
function transpose($array, &$out, $indices = array())
{
if (is_array($array))
{
foreach ($array as $key => $val)
{
//push onto the stack of indices
$temp = $indices;
$temp[] = $key;
transpose($val, $out, $temp);
}
}
else
{
//go through the stack in reverse - make the new array
$ref = &$out;
foreach (array_reverse($indices) as $idx)
$ref = &$ref[$idx];
$ref = $array;
}
}
$foo[1][2][3][3][3] = 'a';
$foo[4][5][6][5][5] = 'b';
$out = array();
transpose($foo, $out);
echo $out[3][3][3][2][1] . ' ' . $out[5][5][6][5][4];
Really hackish, and probably not the best solution, but hey it works.
Basically it traverses the array recursively, accumulating the current indicies in an array.
Once it gets to the referenced value, it takes the "stack" of indices and reverses it, putting it into the $out array. (Is there a way of avoiding use of the $temp array?)
Codler's answer fails for a single-row matrix (e.g. [[1,2]]) and also for the empty matrix ([]), which must be special-cased:
function transpose(array $matrix): array {
if (!$matrix) return [];
return array_map(count($matrix) == 1 ? fn ($x) => [$x] : null, ...$matrix);
}
(note: PHP 7.4+ syntax, easy enough to adapt for older versions)
I got confronted with the same problem. Here is what i came up with:
function array_transpose(array $arr)
{
$keys = array_keys($arr);
$sum = array_values(array_map('count', $arr));
$transposed = array();
for ($i = 0; $i < max($sum); $i ++)
{
$item = array();
foreach ($keys as $key)
{
$item[$key] = array_key_exists($i, $arr[$key]) ? $arr[$key][$i] : NULL;
}
$transposed[] = $item;
}
return $transposed;
}
I needed a transpose function with support for associative array:
$matrix = [
['one' => 1, 'two' => 2],
['one' => 11, 'two' => 22],
['one' => 111, 'two' => 222],
];
$result = \array_transpose($matrix);
$trans = [
'one' => [1, 11, 111],
'two' => [2, 22, 222],
];
And the way back:
$matrix = [
'one' => [1, 11, 111],
'two' => [2, 22, 222],
];
$result = \array_transpose($matrix);
$trans = [
['one' => 1, 'two' => 2],
['one' => 11, 'two' => 22],
['one' => 111, 'two' => 222],
];
The array_unshift trick did not work NOR the array_map...
So I've coded a array_map_join_array function to deal with record keys association:
/**
* Similar to array_map() but tries to join values on intern keys.
* #param callable $callback takes 2 args, the intern key and the list of associated values keyed by array (extern) keys.
* #param array $arrays the list of arrays to map keyed by extern keys NB like call_user_func_array()
* #return array
*/
function array_map_join_array(callable $callback, array $arrays)
{
$keys = [];
// try to list all intern keys
array_walk($arrays, function ($array) use (&$keys) {
$keys = array_merge($keys, array_keys($array));
});
$keys = array_unique($keys);
$res = [];
// for each intern key
foreach ($keys as $key) {
$items = [];
// walk through each array
array_walk($arrays, function ($array, $arrKey) use ($key, &$items) {
if (isset($array[$key])) {
// stack/transpose existing value for intern key with the array (extern) key
$items[$arrKey] = $array[$key];
} else {
// or stack a null value with the array (extern) key
$items[$arrKey] = null;
}
});
// call the callback with intern key and all the associated values keyed with array (extern) keys
$res[$key] = call_user_func($callback, $key, $items);
}
return $res;
}
and array_transpose became obvious:
function array_transpose(array $matrix)
{
return \array_map_join_array(function ($key, $items) {
return $items;
}, $matrix);
}
We can do this by using Two foreach. Traveling one array and another array to create new arrayLike This:
$foo = array(
'a' => array(
1 => 'a1',
2 => 'a2',
3 => 'a3'
),
'b' => array(
1 => 'b1',
2 => 'b2',
3 => 'b3'
),
'c' => array(
1 => 'c1',
2 => 'c2',
3 => 'c3'
)
);
$newFoo = [];
foreach($foo as $a => $k){
foreach($k as $i => $j){
$newFoo[$i][]= $j;
}
}
Check The Output
echo "<pre>";
print_r($newFoo);
echo "</pre>";
Before I start, I'd like to say thanks again to #quazardus for posting his generalised solution for tranposing any two dimenional associative (or non-associative) array!
As I am in the habit of writing my code as tersely as possible I went on to "minimizing" his code a little further. This will very likely not be to everybody's taste. But just in case anyone should be interested, here is my take on his solution:
function arrayMap($cb, array $arrays) // $cb: optional callback function
{ $keys = [];
array_walk($arrays, function ($array) use (&$keys)
{ $keys = array_merge($keys, array_keys($array)); });
$keys = array_unique($keys); $res = [];
foreach ($keys as $key) {
$items = array_map(function ($arr) use ($key)
{return isset($arr[$key]) ? $arr[$key] : null; },$arrays);
$res[$key] = call_user_func(
is_callable($cb) ? $cb
: function($k, $itms){return $itms;},
$key, $items);
}
return $res;
}
Now, analogous to the PHP standard function array_map(), when you call
arrayMap(null,$b);
you will get the desired transposed matrix.
This is another way to do the exact same thing which #codler s answer does. I had to dump some arrays in csv so I used the following function:
function transposeCsvData($data)
{
$ct=0;
foreach($data as $key => $val)
{
//echo count($val);
if($ct< count($val))
$ct=count($val);
}
//echo $ct;
$blank=array_fill(0,$ct,array_fill(0,count($data),null));
//print_r($blank);
$retData = array();
foreach ($data as $row => $columns)
{
foreach ($columns as $row2 => $column2)
{
$retData[$row2][$row] = $column2;
}
}
$final=array();
foreach($retData as $k=>$aval)
{
$final[]=array_replace($blank[$k], $aval);
}
return $final;
}
Test and output reference: https://tutes.in/how-to-transpose-an-array-in-php-with-irregular-subarray-size/
Here is array_walk way to achieve this,
function flipDiagonally($foo){
$temp = [];
array_walk($foo, function($item,$key) use(&$temp){
foreach($item as $k => $v){
$temp[$k][$key] = $v;
}
});
return $temp;
}
$bar = flipDiagonally($foo); // Mystery function
Demo.
Here's a variation of Codler/Andreas's solution that works with associative arrays. Somewhat longer but loop-less purely functional:
<?php
function transpose($array) {
$keys = array_keys($array);
return array_map(function($array) use ($keys) {
return array_combine($keys, $array);
}, array_map(null, ...array_values($array)));
}
Example:
<?php
$foo = array(
"fooA" => [ "a1", "a2", "a3"],
"fooB" => [ "b1", "b2", "b3"],
"fooC" => [ "c1", "c2", "c3"]
);
print_r( transpose( $foo ));
// Output like this:
Array (
[0] => Array (
[fooA] => a1
[fooB] => b1
[fooC] => c1
)
[1] => Array (
[fooA] => a2
[fooB] => b2
[fooC] => c2
)
[2] => Array (
[fooA] => a3
[fooB] => b3
[fooC] => c3
)
);

Categories