dynamically nested array map using php - php

I have an array of list keys like:
$list_map_key=[
['pn','pn1','pp','pp1'],
['pn','pn1','pp','pp2'],
['pn','pn2','pp','pp5'],
['pn','pn2'],
];
I want to build map key array like this to replace value of (pp)
$data_return['pn']['pn1']['pp']['pp1']=3000;
$data_return['pn']['pn1']['pp']['pp2']=3000;
$data_return['pn']['pn2']['pp']['pp5']=3000;
$data_return['pn']['pn2']=3000;
But the keys to the array $data_return['pn']['pn1']['pp']['pp1'] must be dynamically generated from the array key list.
I want to build some function to call position data from list array key and add, replace or delete data.

The exact output you want is not achievable since $data_return['pn']['pn2'] cannot simultaneously be an array and a value. However you can achieve something similar with this code. The function push_value takes an array of keys and pushes the value into a multi-dimensional array according to those keys. Then we generate $data_return by looping over each individual value in $list_map_key and using array_merge_recursive to merge the individual arrays together:
function push_value($keys, $value) {
$key = array_shift($keys);
if (count($keys)) {
return array($key => push_value($keys, $value));
}
else {
return array($key => $value);
}
}
$data_return = array();
$value = 3000;
foreach ($list_map_key as $keys) {
$data_return = array_merge_recursive($data_return, push_value($keys, $value));
}
print_r($data_return);
Output:
Array
(
[pn] => Array
(
[pn1] => Array
(
[pp] => Array
(
[pp1] => 3000
[pp2] => 3000
)
)
[pn2] => Array
(
[pp] => Array
(
[pp5] => 3000
)
[0] => 3000
)
)
)
Demo on 3v4l.org

Related

How to extract element inside an array, which in turn is inside a couple of arrays and display it using a foreach loop

I have a result of a query, which is the name of the image. I am storing the image names for every image Id in an array. Now, on the view page I am using foreach loop to display these images. The problem is I can't extract the elements(the name of the images) from this array.
My array is
Array ( [0] => Array ( [0] => Array ( [picture] => 5a3a13f237715637629.jpeg ) ) [1] => Array ( [0] => Array ( [picture] => 5a3b602654cfd527057.jpg ) ) )
I have used print_r and got this, now I want to extract only the 5a3a13f237715637629.jpeg values and display these using foreach loop on the view page. Any help is welcome.
The simplest way I can think of would be to json the array and then use regex to extract the filenames. You are then left with an array of filenames to loop through and display:
preg_match('/\w+.jpeg/', json_encode($array), $matches);
print_r($matches);
The benefits of doing it this way are that you don't need to know the structure of the array or go through embedded looping to find the values.
If you want do want the loop way; try this:
$array = array(
1 => array(
'picture' => '5a3a13f237715637629.jpeg'
),
2 => array(
'picture' => 'fnofweofweiofniewof.jpeg'
)
);
print_r(search_r($array, 'picture', $results));
function search_r($array, $key, &$results) {
if (!is_array($array)) {
return;
}
if (isset($array[$key])) {
$results[] = $array[$key];
}
foreach ($array as $subarray) {
search_r($subarray, $key, $results);
}
return $results;
}
That will result:
Array
(
[0] => 5a3a13f237715637629.jpeg
[1] => fnofweofweiofniewof.jpeg
)
PS. This is an adaption of this answer

PHP - change index of parent in multi-dimensional array to child array value where key = string

I've got an multi-dimensional array at the moment and want to remove the second-level of arrays and have the value of that second level as the new index value on the parent array. My current array is:
Array ( [0] => Array ( [connectee] => 1 ) [1] => Array ( [connectee] => 6 ) )
And want from that:
Array ( [0] => 1, [1] => 6 )
I was poking around the usort function but couldn't get it to work (where $current_connections is my array as above:
function cmp($a, $b) {
return strcmp($a["connectee"], $b["connectee"]);
}
$current_connections = usort($current_connections, "cmp");
The key doesn't need to be maintained (should be destroyed in the process).
foreach ($array as &$value) {
$value = $value['connectee'];
}
Note: Please note that the question statement is very confusing and contradicting, but this answer is based upon your statement for expected output
Array ( [0] => 1, [1] => 6 )
You could do
<?php
$values=array();
$values[0]=array("connectee"=>1);
$values[1]=array("connectee"=>6);
foreach($values as $index=>$value)
{
$values[$index]=$value["connectee"];
}
print_r($values);
?>

PHP Convert multidimensional array to match format of another

I have two arrays, one is generated by using explode() on a comma separated string and the other is generated from result_array() in Codeigniter.
The results when doing print_r are:
From explode():
Array
(
[0] => keyword
[1] => test
)
From database:
Array
(
[0] => Array
(
[name] => keyword
)
[1] => Array
(
[name] => test
)
)
I need them to match up so I can use array_diff(), what's the best way to get them to match? Is there something other than result_array() in CI to get a compatible array?
You could create a new array like this:
foreach($fromDatabase as $x)
{
$arr[] = $x['name'];
}
Now, you will have two one dim arrays and you can run array_dif.
$new_array = array();
foreach ($array1 as $line) {
$new_array[] = array('name' => $line);
}
print_r($new_array);
That should work for you.

How to shift 2D array in PHP

Hi this is my 2D array format. I want to remove 1st inside array.
Array
(
[0] => Array
(
[0] => Array
(
[type] => section-open
)
)
[1] => Array
(
[0] => Array
(
[type] => section-close
)
)
)
I want to remove all inside array and return it like this
Array
(
[0] => Array
(
[type] => section-open
)
[1] => Array
(
[type] => section-close
)
)
I tried array_shift function it's not working...
Update: This was based on the example the user gave, but he expected it to work for arrays with more than one element.
array_shift() removes the first element of an array, but that's not what you want.
You have to build something yourself.
Something like:
$result = array();
foreach($my_array as $element)
{
$result[]=$element[0];
}
Since you probably want a real 2d shift I made a function which does that, removing the first level in the array, but keeping ALL the items in the second level.
Here is a working example:
http://codepad.org/H7iaTI1E
And the function:
/**
* Removes first level in an array, returning the 2nd level elements as an array
* #param array Array to process
* #return 2nd level items from the given array
*/
function array2dshift(array $array) {
$res = array();
foreach($array as $lvl1) {
foreach($lvl1 as $item) {
$res[] = $item;
}
}
return $res;
}

PHP - Create a single array from a multidimensional array based on key name

I know there are a lot of answers on multi-dimensional arrays but I couldn't find what I was looking for exactly. I'm new to PHP and can't quite get my head around some of the other examples to modify them. If someone could show me the way, it would be much appreciated.
An external service is passing me the following multidimensional array.
$mArray = Array (
[success] => 1
[errors] => 0
[data] => Array (
[0] => Array (
[email] => me#example.com
[id] => 123456
[email_type] => html
[ip_opt] => 10.10.1.1
[ip_signup] =>
[member_rating] => X
[info_changed] => 2011-08-17 08:56:51
[web_id] => 123456789
[language] =>
[merges] => Array (
[EMAIL] => me#example.com
[NAME] => Firstname
[LNAME] => Lastname
[ACCOUNT] => ACME Ltd
[ACCMANID] => 123456adc
[ACCMANTEL] => 1234 123456
[ACCMANMAIL] => an.other#example.com
[ACCMANFN] => Humpty
[ACCMANLN] => Dumpty
)
[status] => unknown
[timestamp] => 2011-08-17 08:56:51
[lists] => Array ( )
[geo] => Array ( )
[clients] => Array ( )
[static_segments] => Array ( )
)
)
)
The only information I'm interested in are the key/value pairs that are held in the array under the key name 'merges'. It's about the third array deep. The key name of the array will always be called merges but there's no guarantee that its location in the array won't be moved. The number of key/value pairs in the merges array is also changeable.
I think what I need is a function for array_walk_recursive($mArray, "myfunction", $search);, where $search holds the string for the Key name (merges) I'm looking for. It needs to walk the array until it finds the key, check that it holds an array and then (preserving the keys), return each key/value pair into a single array.
So, for clarity, the output of the function would return:
$sArray = Array (
[EMAIL] => me#example.com
[NAME] => Firstname
[LNAME] => Lastname
[ACCOUNT] => ACME Ltd
[ACCMANID] => 123456adc
[ACCMANTEL] => 1234 123456
[ACCMANMAIL] => an.other#example.com
[ACCMANFN] => Humpty
[ACCMANLN] => Dumpty
)
I can then move on to the next step in my project, which is to compare the keys in the single merges array to element IDs obtained from an HTML DOM Parser and replace the attribute values with those contained in the single array.
I probably need a foreach loop. I know I can use is_array to verify if $search is an array. It's joining it all together that I'm struggling with.
Thanks for your help.
Would this work?
function find_merges($arr)
{
foreach($arr as $key => $value){
if($key == "merges") return $value;
if(is_array($value)){
$ret = find_merges($value);
if($ret) return $ret;
}
}
return false;
}
It would do a depth-first search until you either ran out of keys or found one with the value merges. It won't check to see if merges is an array though. Try that and let me know if that works.
Here is a general purpose function that will work it's way through a nested array and return the value associated with the first occurance of the supplied key. It allows for integer or string keys. If no matching key is found it returns false.
// return the value a key in the supplied array
function get_keyval($arr,$mykey)
{
foreach($arr as $key => $value){
if((gettype($key) == gettype($mykey)) && ($key == $mykey)) {
return $value;
}
if(is_array($value)){
return get_keyval($value,$mykey);
}
}
return false;
}
// test it out
$myArray = get_keyval($suppliedArray, "merges");
foreach($myArray as $key => $value){
echo "$key = $value\n";
}
A recursive function can do this. Returns the array or FALSE on failure.
function search_sub_array ($array, $search = 'merges') {
if (!is_array($array)) return FALSE; // We're not interested in non-arrays
foreach ($array as $key => $val) { // loop through array elements
if (is_array($val)) { // We're still not interested in non-arrays
if ($key == $search) {
return $val; // We found it, return it
} else if (($result = search_sub_array($array)) !== FALSE) { // We found a sub-array, search that as well
return $result; // We found it, return it
}
}
}
return FALSE; // We didn't find it
}
// Example usage
if (($result = search_sub_array($myArray,'merges')) !== FALSE) {
echo "I found it! ".print_r($result,TRUE);
} else {
echo "I didn't find it :-(";
}
So you want to access an array within an array within an array?
$mergeArray = NULL;
foreach($mArray['data'] as $mmArray)
$mergeArray[] = $mmArray['merges'];
Something like that? If merges is always three deep down, I don't see why you need recursion. Otherwise see the other answers.
Here's another approach, mostly because I haven't used up my iterator quota yet today.
$search = new RegexIterator(
new RecursiveIteratorIterator(
new ParentIterator(new RecursiveArrayIterator($array)),
RecursiveIteratorIterator::SELF_FIRST),
'/^merges$/D', RegexIterator::MATCH, RegexIterator::USE_KEY
);
$search->rewind();
$merges = $search->current();
array_walk_recursive() is brilliant for this task! It doesn't care what level the key-value pairs are on and it only iterates the "leaf nodes" so there is not need to check if an element contains a string. Inside of the function, I am merely making a comparison on keys versus the array of needles to generate a one-dimensional result array ($sArray).
To be clear, I am making an assumption that you have predictable keys in your merges subarray.
Code: (Demo)
$needles=['EMAIL','NAME','LNAME','ACCOUNT','ACCMANID','ACCMANTEL','ACCMANMAIL','ACCMANFN','ACCMANLN'];
array_walk_recursive($mArray,function($v,$k)use(&$sArray,$needles){if(in_array($k,$needles))$sArray[$k]=$v;});
var_export($sArray);
Output:
array (
'EMAIL' => 'me#example.com',
'NAME' => 'Firstname',
'LNAME' => 'Lastname',
'ACCOUNT' => 'ACME Ltd',
'ACCMANID' => '123456adc',
'ACCMANTEL' => '1234 123456',
'ACCMANMAIL' => 'an.other#example.com',
'ACCMANFN' => 'Humpty',
'ACCMANLN' => 'Dumpty',
)

Categories