I have two arrays :
groups = array (
array (1 => string 'INFORMATIQUE ET MULTIMEDIA'),
array (2 => string 'VEHICULES' ),
array (3 => string 'IMMOBILIER' ),
array (4 => string 'POUR LA MAISON ET JARDIN'),
array (5 => string 'HABILLEMENT ET BIEN ETRE'),
array (6 => string 'LOISIRS ET DIVERTISSEMENT'),
array (7 => string 'EMPLOI ET SERVICE' ),
array (8 => string 'ENTREPRISE' ),
array (9 => string 'AUTRES' ));
This is an array of categories groups
I have in the other side an array of categories :
$categories = array (
array (
'id' => string '1' ,
'name' => string 'Téléphones' ,
'groupid' => string '1'
),
array (
'id' => string '2',
'name' => string 'Tablette' ,
'groupid' => string '1'
),
array (
'id' => string '3' ,
'name' => string 'Voitures' ,
'groupid' => string '2'
),
array (
'id' => string '4' ,
'name' => string 'Motos',
'groupid' => string '2'
)
);
What i want is :
$result = array (
'INFORMATIQUE ET MULTIMEDIA' =>
array (
1 => string 'Téléphones',
2 => string 'Tablette'
)
'VEHICULES' =>
array (
4 => string 'Motos',
4 => string 'Motos'
)
);
This is my code but it doesn't work but the problem is that it records a single line :
foreach($groups as $id => $name)
{
$n = 1;
foreach($categories as $k=>$v)
{
if($v['groupid'] == $id){
$result[$name] = array_fill($v['id'], 1, $v['name']);
$n ++;
}
}
}
try this code, it will work for you
<?php
$result = null;
foreach($goups as $key => $value)
foreach($categories as $categorie)
if( $key == $categorie['groupid'] )
$result[$value][] = $categorie['name']
?>
foreach($groups as $id => $name)
{
foreach($categories as $k=>$v)
{
if($v['groupid'] == $id){
$result[$name][] = array($v['id'] => $v['name']);
}
}
}
or a simple one.
foreach($categories as $k=>$v)
{
$result[$groups[$v['groupid']]][] = array($v['id'] => $v['name']);
}
You got most of the code right, but you keep assigning all your data in the first index of your sub-array, which is why you get one single result. Try the code below
foreach($groups as $id => $name)
{
$n = 1;
foreach($categories as $k=>$v)
{
if($v['groupid'] == $id){
$result[$name][$n] = $['name'];
$n++;
}
}
}
Related
Over the past few days, I've been thinking about how to deal with iterating over keys in a multidimensional array, and I just cannot figure it out. The problem is, I don't know how deep the array might be - I want my code to be able to handle arrays of any depth.
The array itself comes from Advanced Custom Fields, but that's not too important. I need to iterate over the array, run a function on every array key which starts with field_ (to convert it from field_* to its proper name like post_title or something), and reconstruct the array with the same structure and values (although the order is not important). The array looks like this:
array (size=12)
'field_5b23d04fef8a6' => string '' (length=0)
'field_5b23d04fefa99' => string '' (length=0)
'field_5b23d04fefe85' => string '' (length=0)
'field_5b23d04ff0077' => string '' (length=0)
'field_5b23d04ff026c' => string '' (length=0)
'field_5b23d0bdb3c1a' => string 'Version 1' (length=9)
'field_5b23d0f48538b' => string '' (length=0)
'field_5b23d0f485772' => string '' (length=0)
'field_5b23d0d52be2d' => string '' (length=0)
'field_5b5ed10a6a7bc' => string '' (length=0)
'field_5b5ed10a6bcf5' =>
array (size=1)
0 =>
array (size=1)
'field_5b5ed10acd264' =>
array (size=1)
0 =>
array (size=6)
'field_5b5ed10b0c9ca' => string '0' (length=1)
'field_5b5ed10b0cce2' => string 'TEST1234' (length=8)
'field_5b5ed10b0d0fd' => string 'Download title' (length=14)
'field_5b5ed10b0d4e2' => string 'EN' (length=2)
'field_5b5ed10b0d72e' => string 'A00' (length=3)
'field_5b5ed10b0df27' => string '887' (length=3)
'field_5b23d088500a4' => string '' (length=0)
What would be the best way to handle this? I've looked at recursive functions and ResursiveArrayIterator already, but none of the examples I found were close enough to let me figure out what I need.
You can recursively call the same function if it finds a nested array like this:
$input = array(
'field_5b23d04fef8a6' => '',
'field_5b23d04fefa99' => '',
'field_5b23d04fefe85' => '',
'field_5b23d04ff0077' => '',
'field_5b23d04ff026c' => '',
'field_5b23d0bdb3c1a' => 'Version 1',
'field_5b23d0f48538b' => '',
'field_5b23d0f485772' => '',
'field_5b23d0d52be2d' => '',
'field_5b5ed10a6a7bc' => '',
'field_5b5ed10a6bcf5' => array(
array(
'field_5b5ed10acd264' => array(
array(
'field_5b5ed10b0c9ca' => '0',
'field_5b5ed10b0cce2' => 'TEST1234',
'field_5b5ed10b0d0fd' => 'Download title',
'field_5b5ed10b0d4e2' => 'EN',
'field_5b5ed10b0d72e' => 'A00',
'field_5b5ed10b0df27' => '887',
),
),
),
),
'field_5b23d088500a4' => '',
);
// recursively re-key array
function dostuff($input){
// always refer to self, even if you rename the function
$thisfunction = __function__;
$output = array();
foreach($input as $key => $value){
// change key
$newkey = (is_string($key) ? preg_replace('/^field_/', 'post_title_', $key) : $key);
// iterate on arrays
if(is_array($value)){
$value = $thisfunction($value);
}
$output[$newkey] = $value;
}
return $output;
}
var_dump(dostuff($input));
So I was looking at this and to my knowledge there is no wrapper function for recursion with callbacks, so here it is:
// general function for recursively doing something
// $input -> array() / the array you wan to process
// $valuefunction -> callable | null / function to run on all values *
// $keyfunction -> callable | null / function to run on all keys *
// * at least one has to defined or there is nothing to do
// callable has two inputs
// $input -> current branch
// $depth -> (int) how deep in the structure are we
// i.e: recursion($some_array, function($branch, $depth){something..}, 'trim');
function recursion($input, $valuefunction = false, $keyfunction = false){
if(!is_array($input)){
trigger_error('Input is '.gettype($input).'. Array expected', E_USER_ERROR);
return null;
}
if(!is_callable($valuefunction)){$valuefunction = false;}
if(!is_callable($keyfunction)){$keyfunction = false;}
if(!$valuefunction && !$keyfunction){
trigger_error('Input is unchanged!', E_USER_WARNING);
return $input;
}
// use recursion internally, so I can pass stuff by reference
// and do the above checks only once.
$recurse = function(&$branch, $depth = 0) use (&$recurse, &$valuefunction, &$keyfunction){
$output = array();
foreach($branch as $key => $value){
$key = $keyfunction ? $keyfunction($key, $depth) : $key;
$output[$key] = (is_array($value) ?
$recurse($value, $depth + 1) :
($valuefunction ?
$valuefunction($value, $depth) :
$value
)
);
}
return $output;
};
return $recurse($input);
}
$valuefunction = function($value, $depth){
return is_string($value) ? $depth.'_'.$value : $value;
};
function keyfunction($key){
return is_string($key) ? preg_replace('/^field_/', 'post_title_', $key) : $key;
}
var_dump(recursion($input, $valuefunction, 'keyfunction'));
Or for your example:
var_dump(recursion($input, 0, function($key){
return is_string($key) ? preg_replace('/^field_/', 'post_title_', $key) : $key;
}));
You could do something like this:
$arr = [
'a',
'b',
'c',
[
'd',
'e',
'f',
[
'g',
'h',
'i',
],
],
];
class MyIterator
{
public function iterate( $array )
{
foreach ( $array as $a ) {
if ( is_array( $a ) ) {
$this->iterate($a);
} else {
echo $a;
}
}
}
}
$iterator = new MyIterator();
$iterator->iterate($arr);
It prints this:
abcdefghi
You can iterate over array recursively like this
function recursiveWalk($array, callable $x)
{
$result = [];
foreach ($array as $key => $value) {
if (is_array($value)) {
$result[$key] = recursiveWalk($value, $x);
} else {
$result[$key] = $x($value);
}
}
return $result;
}
Here example:
$array = [
"aaa" => 1,
"sub1" => [
"xxx" => 2,
"sub2" => [
"yyy" => 3,
"ttt" => 4
]
]
];
print_r(recursiveWalk($array, function ($x) {
return $x + 1;
}));
Array
(
[aaa] => 2
[sub1] => Array
(
[xxx] => 3
[sub2] => Array
(
[yyy] => 4
[ttt] => 5
)
)
)
I'm trying to add arrays to an associative array in PHP. I know this isn't how you're supposed to use the keys but I'm parsing the array to XML which needs te same <line> tag.
Desired array:
array(
'line' => array(
// Ean-artikelcode
'Article_Eancode' => 8710624618216,
// Leveranciersartikelcode
'Article_Supplier_Partno' => 22304
),
'line' => array(
'Article_Eancode' => 8710622648216,
'Article_Supplier_Partno' => 22304
)
);
Which I am trying to get with this code:
$artikelenFormatted = array();
$artikelen = array(
'a',
'b',
'c'
);
foreach ($artikelen as $art) {
$artikelenFormatted['line'] = array(
"Article_Eancode" => "a",
"Article_Supplier_Partno" => "b"
);
}
Which produces:
array (size=1)
'line' =>
array (size=2)
'Article_Eancode' => string 'a' (length=1)
'Article_Supplier_Partno' => string 'b' (length=1)
Because $array['line'] keeps getting overwritten so there aren't multiple entries
How would I do this?
EDIT: Sample of the desired XML
<Lines>
<Line>
<Article_Eancode>87XXXXXXXXXXX</Article_Eancode>
<Article_Supplier_Partno>22304</Article_Supplier_Partno>
</Line>
<Line>
<Article_Eancode>87XXXXXXXXXXX</Article_Eancode>
<Article_Supplier_Partno>22303</Article_Supplier_Partno>
</Line>
<Line>
<Article_Eancode>87XXXXXXXXXXX</Article_Eancode>
<Article_Supplier_Partno>22324</Article_Supplier_Partno>
</Line>
<Line>
<Article_Eancode>87XXXXXXXXXXX</Article_Eancode>
<Article_Supplier_Partno>22305</Article_Supplier_Partno>
</Line>
<Line>
<Article_Eancode>87XXXXXXXXXXX</Article_Eancode>
<Article_Supplier_Partno>22323</Article_Supplier_Partno>
</Line>
</Lines>
An array cannot have two (or more) of the same key. Consider; what would $array['line'] return?
What you're looking for is:
foreach ($artikelen as $art) {
$artikelenFormatted['line'][] = array(
"Article_Eancode" => "a",
"Article_Supplier_Partno" => "b"
);
}
Notice the [] after ['line']. This will make $artikelenFormatted['line'] an array where each element is an array of the data.
Edit:
To get it to work with XML, use the following:
foreach ($artikelen as $art) {
$artikelenFormatted[]['line'] = array(
"Article_Eancode" => "a",
"Article_Supplier_Partno" => "b"
);
}
And amend the array_to_xml function you reference to:
function new_array_to_xml( $data, &$xml_data ) {
foreach( $data as $key => $value ) {
if( is_array($value) ) {
if( is_numeric($key) ){
array_to_xml($value, $xml_data);
}
else
{
$subnode = $xml_data->addChild($key);
array_to_xml($value, $subnode);
}
} else {
$xml_data->addChild("$key",htmlspecialchars("$value"));
}
}
}
I solved this by using:
foreach ( $artikelen as $art ) {
$artikelenFormatted [] = array (
"Article_Eancode" => "a",
"Article_Supplier_Partno" => "b"
);
Which would output
array (size=2)
0 =>
array (size=2)
'Article_Eancode' => string 'a' (length=1)
'Article_Supplier_Partno' => string 'b' (length=1)
1 =>
array (size=2)
'Article_Eancode' => string 'a' (length=1)
'Article_Supplier_Partno' => string 'b' (length=1)
And editing my array_to_xml() function to change numeric keys to the string 'line' which produces the right XML
private function array_to_xml($entries, &$tmpXML) {
foreach ( $entries as $key => $value ) {
if (is_array ( $value )) {
if (! is_numeric ( $key )) {
$subnode = $tmpXML->addChild ( "$key" );
$this->array_to_xml ( $value, $subnode );
} else {
$subnode = $tmpXML->addChild ( "line" );
$this->array_to_xml ( $value, $subnode );
}
} else {
$tmpXML->addChild ( "$key", htmlspecialchars ( "$value" ) );
}
}
}
Thanks for everyone's input
You can't have the same keys but you can have :
EDIT 1 :
array(
[0] => array(
'line' => array(
// Ean-artikelcode
'Article_Eancode' => 8710624618216,
// Leveranciersartikelcode
'Article_Supplier_Partno' => 22304
)),
[1] => array(
'line' => array(
'Article_Eancode' => 8710622648216,
'Article_Supplier_Partno' => 22304
))
);
And you can do it like this :
foreach ($artikelen as $art) {
$artikelenFormatted[] = array(
'line' => array(
"Article_Eancode" => "a",
"Article_Supplier_Partno" => "b"
);
}
I want to delete array index which contain rating 0 here is my array
array(
(int) 0 => array(
'Gig' => array(
'id' => '1',
'rating' => (int) 5
)
),
(int) 1 => array(
'Gig' => array(
'id' => '3',
'rating' => (int) 9
)
),
(int) 2 => array(
'Gig' => array(
'id' => '4',
'rating' => '0'
)
)
)
and what I did
for($i = 0; $i<count($agetGigsItem); $i++)
{
if($agetGigsItem[$i]['Gig']['rating']==0)
{
unset($agetGigsItem[$i]);
}
$this->set('agetGigsItem', $agetGigsItem);
}
i also try foreach loop but unable to resolve this issue.
foreach ($agetGigsItem as $key => $value) {
if ($value["Gig"]["rating"] == 0) { unset($agetGigsItem[$key]); }
}
I think you need to reupdate your array.
foreach ($agetGigsItem as $key => $value) {
if ($value["Gig"]["rating"] != 0)
{
unset($agetGigsItem[$key]);
}
$this->set('agetGigsItem', $agetGigsItem);
}
I hope you are missing $this and so you cannot access the array in CakePHP.
So try this:
foreach ($this->$agetGigsItem as $key => $value) {
if ($value["Gig"]["rating"] == 0) {
unset($this->$agetGigsItem[$key]);
}
}
This code will unset arrey index with value 0.
<?php
$array=array(
array(
'Gig' => array(
'id' => '1',
'rating' =>5
)
),
array(
'Gig' => array(
'id' => '3',
'rating' =>9
)
),
array(
'Gig' => array(
'id' => '4',
'rating' =>0
)
)
);
foreach($array as $a){
if($a['Gig']['rating']==0){
unset($a['Gig']['rating']);
}
$array1[]=$a;
}
var_dump($array1);
Destroying occurances within an array you are actually processing over with a for or a foreach is always a bad idea. Each time you destroy an occurance the loop can easily get corrupted and get in a terrible mess.
If you want to remove items from an array it is better to create a copy of the array and process over that new array in the loop but remove the items from the original array.
So try this instead
$tmparray = $this->agetGigsItem; // will copy agetGigsItem into new array
foreach ($tmparray as $key => $value) {
if ($value["Gig"]["rating"] == 0) {
unset($this->agetGigsItem[$key]);
}
}
unset($tmparray);
when searching an element in a nested array, could i get back it's 1st level nesting index.
<?php
static $cnt = 0;
$name = 'victor';
$coll = array(
'dep1' => array(
'fy' => array('john', 'johnny', 'victor'),
'sy' => array('david', 'arthur'),
'ty' => array('sam', 'joe', 'victor')
),
'dep2' => array(
'fy' => array('natalie', 'linda', 'molly'),
'sy' => array('katie', 'helen', 'sam', 'ravi', 'vipul'),
'ty' => array('sharon', 'julia', 'maddy')
)
);
function recursive_search(&$v, $k, $search_query){
global $cnt;
if($v == $search_query){
/* i want the sub array index to be returned */
}
}
?>
i.e to say, if i'am searching 'victor', i would like to have 'dep1' as the return value.
Could anyone help ??
Try:
$name = 'victor';
$coll = array(
'dep1' => array(
'fy' => array('john', 'johnny', 'victor'),
'sy' => array('david', 'arthur'),
'ty' => array('sam', 'joe', 'victor')
),
'dep2' => array(
'fy' => array('natalie', 'linda', 'molly'),
'sy' => array('katie', 'helen', 'sam', 'ravi', 'vipul'),
'ty' => array('sharon', 'julia', 'maddy')
)
);
$iter = new RecursiveIteratorIterator(new RecursiveArrayIterator($coll), RecursiveIteratorIterator::SELF_FIRST);
/* These will be used to keep a record of the
current parent element it's accessing the childs of */
$parent_index = 0;
$parent = '';
$parent_keys = array_keys($coll); //getting the first level keys like dep1,dep2
$size = sizeof($parent_keys);
$flag=0; //to check if value has been found
foreach ($iter as $k=>$val) {
//if dep1 matches, record it until it shifts to dep2
if($k === $parent_keys[$parent_index]){
$parent = $k;
//making sure the counter is not incremented
//more than the number of elements present
($parent_index<$size-1)?$parent_index++:'';
}
if ($val == $name) {
//if the value is found, set flag and break the loop
$flag = 1;
break;
}
}
($flag==0)?$parent='':''; //this means the search string could not be found
echo 'Key = '.$parent;
Demo
This works , but I don't know if you are ok with this...
<?php
$name = 'linda';
$col1=array ( 'dep1' => array ( 'fy' => array ( 0 => 'john', 1 => 'johnny', 2 => 'victor', ), 'sy' => array ( 0 => 'david', 1 => 'arthur', ), 'ty' => array ( 0 => 'sam', 1 => 'joe', 2 => 'victor', ), ), 'dep2' => array ( 'fy' => array ( 0 => 'natalie', 1 => 'linda', 2 => 'molly', ), 'sy' => array ( 0 => 'katie', 1 => 'helen', 2 => 'sam', 3 => 'ravi', 4 => 'vipul', ), 'ty' => array ( 0 => 'sharon', 1 => 'julia', 2 => 'maddy', ), ), );
foreach($col2 as $k=>$arr)
{
foreach($arr as $k1=>$arr2)
{
if(in_array($name,$arr2))
{
echo $k;
break;
}
}
}
OUTPUT :
dept2
Demo
I've here two multi-dimensional arrays.
How would you do to get the image_to_get value in the $b array thanks to the $a array ?
$a = array(
'thumbs' => array(
'0' => array(
'thumb1a' => array(
'0' => array(
'thumb1' => ""
)
)
)
)
);
$b = array(
'thumbs' => array(
'0' => array(
'thumb1a' => array(
'0' => array(
'thumb1' => "image_to_get"
)
),
'thumb2' => 'image2',
'thumb3' => 'image3',
'thumb4' => 'image4',
'thumb5' => 'image5',
)
)
);
You can try with:
function getAPath($array) {
if (empty($array)) {
return array();
}
$key = key($array);
return array_merge(array($key), getAPath($array[$key]));
}
function getBValue($array, $path) {
$key = array_shift($path);
if (is_null($key) || empty($array)) {
return $array;
}
return getBValue($array[$key], $path);
}
$aPath = getAPath($a);
$bValue = getBValue($b, $aPath);
var_dump($bValue);
First function getAPath flatterns your $a array into:
array (size=5)
0 => string 'thumbs' (length=6)
1 => int 0
2 => string 'thumb1a' (length=7)
3 => int 0
4 => string 'thumb1' (length=6)
Second function getBValue walks through the $b array using $aPath.
Below lovely one-liners ;-)
function getAPath($array) {
return empty($array) ? array() : array_merge(array($key = key($array)), getAPath($array[$key]));
}
function getBValue($array, $path) {
return (is_null($key = array_shift($path)) || empty($array)) ? $array : getBValue($array[$key], $path);
}