I have array like the following
Array ( [0] => Array ( [0] => 5 ) [1] => Array ( [0] => 6 [1] => 7 ) )
Now I want only values of this two dimensional array
The result should be array(5,6,7)
Bit of a hack/neat trick depending on how you look at it ;)
$result = call_user_func_array('array_merge', $a);
You're looking for array_values() which returns an array of all array values, sans-keys.
http://php.net/manual/en/function.array-values.php
Update:
Alternatively for an already multi-dimensional array, you can use the following recursive function (borrowed from http://davidwalsh.name/flatten-nested-arrays-php):
function array_flatten($array,$return)
{
for($x = 0; $x <= count($array); $x++)
{
if(is_array($array[$x]))
{
$return = array_flatten($array[$x],$return);
}
else
{
if($array[$x])
{
$return[] = $array[$x];
}
}
}
return $return;
}
Something like this
array_merge($a[0], $a[1]);
function flattenArray($array) {
$flattened = array();
foreach($array as $value) {
if (is_array($value)) {
$flattened = array_merge($flattened, flattenArray($value));
} else {
$flattened[] = $value;
}
}
return $flattened;
}
$array = array(1, array(2, 3), array(4, array(5, 6)));
var_dump($array, flattenArray($array));
Output
array(3) {
[0]=>
int(1)
[1]=>
array(2) {
[0]=>
int(2)
[1]=>
int(3)
}
[2]=>
array(2) {
[0]=>
int(4)
[1]=>
array(2) {
[0]=>
int(5)
[1]=>
int(6)
}
}
}
array(6) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
[5]=>
int(6)
}
CodePad.
$result = array();
foreach($parentArray as $pa)
{
if(is_array($pa))
$result= array_merge($result, $pa);
else
$result[] = $pa;
}
Use $result.
Related
I know this is asked a lot, but I can't get it to work correctly.
What I have
A PHP function that get's the page id (fk_page).
Inside this function the same function is called to look for child pages.
My Database looks like this:
The PHP Code looks like this:
private function createNav($parent = 0, $sub = false) {
// *!* Create Nav
$getNavPage = $this->model->loadNav($parent); // array of menu items (fk_page) that have $parent as parent.
$NavPage = 0;
foreach ($getNavPage as $getPage) {
$NavPage = intval($getPage["fk_page"]);
$subnav = $this->createNav($NavPage, true); // get childs (recursive loop) and save fk_page in $subnav
if($sub === false) $this->navArr[$parent][] = $NavPage;
else $this->navArr[$parent][][] = $NavPage;
}
return $NavPage;
}
The model does the following
public function loadNav($parent) {
$stmt = $this->pdo->prepare("SELECT fk_page FROM nav WHERE fk_parentpage = " . $parent . ";");
$stmt->execute();
return $stmt->fetchAll();
}
Now the result is an array that looks like this
array(3) {
[0]=>
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
[2]=>
array(1) {
[0]=>
array(1) {
[0]=>
int(4)
}
}
[3]=>
array(2) {
[0]=>
array(1) {
[0]=>
int(5)
}
[1]=>
array(1) {
[0]=>
int(6)
}
}
}
What I would like to have as a result:
array(3) {
[0]=>
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
array(1) {
[0]=>
array(1) {
[0]=>
int(4)
}
}
[3]=>
array(2) {
[0]=>
array(1) {
[0]=>
int(5)
}
[1]=>
array(1) {
[0]=>
int(6)
}
}
}
}
I believe that the createNav() must run before the array element is written (or even inside the array $this->NavArr), but I wasn't really succesfull.
Here is an example that uses local data but mimics what you're trying to do:
$data_array = array(
0 => array(1, 2, 3)
, 2 => array(4)
, 3 => array(5, 6)
);
function get_kids($id = 0) {
global $data_array;
if(isset($data_array[$id])) {
return $data_array[$id];
}
else {
return array();
}
}
function create_navigation($parent_id = 0) {
// Check for children
$children_array = get_kids($parent_id);
// No children - just return the parent
if (empty($children_array)) {
return $parent_id;
}
// Children!
foreach ($children_array as $key => $child_id) {
$children_array[$key] = create_navigation($child_id);
}
return array($parent_id => $children_array);
}
echo '<pre>';
$nav = create_navigation(0);
var_dump($nav);
print_r($nav);
echo '</pre>';
The $data_array is used instead of your database.
The get_kids function is your loadNav method.
The create_navigation function is your createNav method.
This produces a var_dump:
array(1) {
[0]=>
array(3) {
[0]=>
int(1)
[1]=>
array(1) {
[2]=>
array(1) {
[0]=>
int(4)
}
}
[2]=>
array(1) {
[3]=>
array(2) {
[0]=>
int(5)
[1]=>
int(6)
}
}
}
}
And a print_r:
Array
(
[0] => Array
(
[0] => 1
[1] => Array
(
[2] => Array
(
[0] => 4
)
)
[2] => Array
(
[3] => Array
(
[0] => 5
[1] => 6
)
)
)
)
The problem with your original code is you were assigning IDs to the class variable $this->navArr instead of using recursion to return the child elements ($subnav).
I have two array, arrLevel1 and arrLevel2.
I want to count animal that can walk.
How can I do that array stucture like this?
Thx before. I already tried, but it failed.
arrLevel1:
array(4) {
[0]=>
array(1) {
["Walk"]=>
string(4) "Bird"
}
[1]=>
array(1) {
["Walk"]=>
string(3) "Cat"
}
[2]=>
array(1) {
["Fly"]=>
string(9) "ButterFLy"
}
[3]=>
array(1) {
["Fly"]=>
string(4) "Bird"
}
}
arrLevel2:
array(3) {
[0]=>
array(1) {
["Animal"]=>
string(3) "Fly"
}
[1]=>
array(1) {
["Animal"]=>
string(11) "Walk"
}
[2]=>
array(1) {
["Human"]=>
string(11) "Walk"
}
}
Just check them in a loop
For the first arrLevel1:
<?php
$arrLevel1 = array(array("walk"=>"Bird"),array("walk"=>"Cat"),array("Fly"=>"Butterfly"),array("Fly"=>"Bird"));
$x = 0;
foreach($arrLevel1 as $p){
if($p["walk"]!==null){
$x++;
}
}
var_dump($x);
?>
Hope thsi helps you
One way to do it is using array_reduce():
$array = array(array('Walk' => 'Bird'), array('Walk' => 'Cat'), array('Fly' => 'ButterFly'), array('Fly' => 'Bird'));
$count = array_reduce($array, function($carry, $item) {
return key($item) == 'Walk' ? $carry + 1 : $carry;
}, 0);
var_dump($count);
You can use a similar code for the second version:
$array = array(array('Animal' => 'Fly'), array('Animal' => 'Walk'), array('Human' => 'Walk'));
$count = array_reduce($array, function($carry, $item) {
return reset($item) == 'Walk' ? $carry + 1 : $carry;
}, 0);
var_dump($count);
$i=0;
$array=array("one","two");
foreach($array as &$point)
{
$point[$i]=array($point[$i], $i);
$i++;
}
var_dump($array);
yields:
array(2) { [0]=> string(3) "Ane" [1]=> &string(3) "tAo" }
I was expecting something more like:
[0]=> [0]=> "one" [1]= 1
[1]=> [0]=> "two" [1]= 2
Am I doing the inner block of the foreach wrong, or is there another method I should be using to go from a single to a 2D array?
You mean like this:
$i=1;
$array=array("one","two");
foreach($array as $j => $point)
{
$array[$j]=array($point, $i);
$i++;
}
var_dump($array);
Outputs:
array(2) {
[0]=>
array(2) {
[0]=>
string(3) "one"
[1]=>
int(1)
}
[1]=>
array(2) {
[0]=>
string(3) "two"
[1]=>
int(2)
}
}
$array = array("one","two");
foreach($array as $i => &$point)
{
$point = array($point, $i + 1);
}
var_dump($array);
There were several errors in your code:
You should assign to $point
You should access $point, not $point[$i]
If you had error output turned on (or of you look at the error logs) you'd see Array to string conversion error for your code.
You may use this to define a two dimensional array in PHP
$array = array(
array(0, 1, 2),
array(3, 4, 5),
);
I need to split the following
$str = 'min(5,6,7,88),email'
$str= 'min(5,6,7,88),!email,max(6,5),alpha_numeric,required'//other possibilities
so it returns an array like so:
array(
[0]=>array(
[0]=>'min',
[1]=>array(5,6,7,88)
)
[1]=>array(
[0]=>'email'
)
)
is this possible ? btw email and min could be anything really , aswell as 5 6 7 88
I think preg_match is best suited for this particular case. However, preg_match alone cannot format the output as you want it.
preg_match('/(\w+)\(([0-9,]+)\),(\w+)+/', $str, $values);
$output = array(
array($values[1], explode(',', $values[2])),
array($values[3]),
);
Given the following:
$test = "min(5,6,7,88),email";
$_ = null;
if (preg_match('/^(?<first>\w+)\((?<array>(?:[0-9]+\x2C*)+)\)\x2C(?<last>\w+)$/',$test,$_))
{
$result = Array(
Array($_['first'],explode(',',$_['array'])),
Array($_['last'])
);
print_r($result);
}
Renders the following result:
Array
(
[0] => Array
(
[0] => min
[1] => Array
(
[0] => 5
[1] => 6
[2] => 7
[3] => 88
)
)
[1] => Array
(
[0] => email
)
)
function parse($str) {
$str = str_replace(array('(',')'),"0x00",$str);
$strArray = explode("0x00",$str);
$tokens = array();
$tokenRef = 0;
foreach($strArray as $tokenID => $tokenValue) {
if (($tokenID % 2) == 1) {
--$tokenRef;
$tokens[$tokenRef++][1] = '('.$tokenValue.')';
} else {
$tokenList = explode(",",$tokenValue);
foreach($tokenList as $token) {
if ($token != '') {
$tokens[$tokenRef++][0] = $token;
}
}
}
}
return $tokens;
}
$str = 'min(5,6,7,88),email';
$split = parse($str);
echo '<pre>';
var_dump($split);
echo '</pre>';
echo '<br />';
$str = 'min(5,6,7,88),!email,max(6,5),alpha_numeric,required';
$split = parse($str);
echo '<pre>';
var_dump($split);
echo '</pre>';
echo '<br />';
Gives
array(2) {
[0]=>
array(2) {
[0]=>
string(3) "min"
[1]=>
string(10) "(5,6,7,88)"
}
[1]=>
array(1) {
[0]=>
string(5) "email"
}
}
and
array(5) {
[0]=>
array(2) {
[0]=>
string(3) "min"
[1]=>
string(10) "(5,6,7,88)"
}
[1]=>
array(1) {
[0]=>
string(6) "!email"
}
[2]=>
array(2) {
[0]=>
string(3) "max"
[1]=>
string(5) "(6,5)"
}
[3]=>
array(1) {
[0]=>
string(13) "alpha_numeric"
}
[4]=>
array(1) {
[0]=>
string(8) "required"
}
}
So I'm suppose to build a multidimensional array dynamically from a text file, and everything works perfectly except that the numeric keys are screwing me over...
The text file looks something like this:
a=1
b.c=2
b.d.0.e=3
b.d.0.f=4
b.d.1.e=5
b.d.1.f=6
As the array_merge_recursive doesn't work with numeric keys, the output is like:
array(2) {
["a"]=>
string(3) "1"
["b"]=>
array(2) {
["c"]=>
string(3) "2"
["d"]=>
array(4) {
[0]=>
array(1) {
["e"]=>
string(9) "3"
}
[1]=>
array(1) {
["f"]=>
string(4) "4"
}
[2]=> array(1) {
["e"]=>
string(8) "5"
}
[3]=>
array(1) {
["f"]=>
string(9) "6"
}}}}
Is there any easy solution to make the output like...?
array(2) {
["a"]=>
string(3) "1"
["b"]=>
array(2) {
["c"]=>
string(3) "2"
["d"]=>
array(2) {
[0]=>
array(2) {
["e"]=>
string(9) "3"
["f"]=>
string(4) "4"
}
[1]=>
array(3) {
["e"]=>
string(9) "5"
["f"]=>
string(4) "6"
}}}}
Thanks
You could break each bit into its components and build up the array one step at a time.
$path = "b.d.0.e";
$val = 3;
$output = array();
$parts = explode(".", $path);
// store a pointer to where we currently are in the array.
$curr =& $output;
// loop through up to the second last $part
for ($i = 0, $l = count($parts); $i < $l - 1; ++$i) {
$part = $parts[$i];
// convert numeric strings into integers
if (is_numeric($part)) {
$part = (int) $part;
}
// if we haven't visited here before, make an array
if (!isset($curr[$part])) {
$curr[$part] = array();
}
// jump to the next step
$curr =& $curr[$part];
}
// finally set the value
$curr[$parts[$l - 1]] = $val;
My output, using the same input as yours:
Array (
[a] => 1
[b] => Array (
[c] => 2
[d] => Array (
[0] => Array (
[e] => 3
[f] => 4
)
[1] => Array (
[g] => 5
[h] => 6
)
)
)
)
Or you could use eval():
$raw_data = file($txt_file, FILE_IGNORE_NEW_LINES);
foreach ($raw_data as $line) {
list($keys, $value) = explode('=', $line);
$keys = explode('.', $keys);
$arr_str = '$result';
foreach ($keys as $key) {
if (ctype_digit($key)) {
$arr_str .= "[" . $key . "]";
} else {
$arr_str .= "['" . $key . "']";
}
}
eval($arr_str . ' = $value;');
}
print_r($result);
I know this is an old one, but the best solution I have found is to use array_replace_recursive. It will achieve what you are looking to do:
$start = array(
"600" => array("total" => 100),
"700" => array("total" => 200)
);
$finish = array(
"600" => array("average" => 25),
"700" => array("average" => 50)
);
$out = array_replace_recursive($start,$finish);
var_dump($out):
array(2) {
[600]=>
array(2) {
["total"]=>
int(100)
["average"]=>
int(25)
}
[700]=>
array(2) {
["total"]=>
int(200)
["average"]=>
int(50)
}
}