PHP - array key within array value - php

I have a PHP array like this:
$arr = array(
'id' => 'app.settings.value.id',
'title' => 'app.settings.value.title',
'user' => 'app.settings.value.user'
);
I want to remove '.id', '.title' and '.user' in the array values. I want to insert the key of this array at the end of the value. I know, that I can get an array key by passing an array and a value to 'array_search', but I want the key within this one array definition - at the end of it's value. Is this possible?

I don't like this, but I guess it's simple and works:
$arr = array(
'id' => 'app.settings.value',
'title' => 'app.settings.value',
'user' => 'app.settings.value'
);
$result = array();
foreach ($arr AS $key => $value) {
$result[$key] = $value . '.' . $key;
}
You're storing app.settings.value which is the same for all array items, so personally I'd prefer:
$arr = array(
'id',
'title',
'user'
);
function prepend_key($key)
{
return 'app.settings.value.' . $key;
}
$result = array_map('prepend_key', $arr);
With $result containing:
array(
'app.settings.value.id',
'app.settings.value.title',
'app.settings.value.user'
);
At the end of the day, either works :)

Related

Loop over one array as if it was a multidimensional array

I have an array like:
$array = array(
'name' => 'Humphrey',
'email' => 'humphrey#wilkins.com
);
This is retrieved through a function that gets from the database. If there is more than one result retrieved, it looks like:
$array = array(
[0] => array(
'name' => 'Humphrey1',
'email' => 'humphrey1#wilkins.com'
),
[1] => array(
'name' => 'Humphrey2',
'email' => 'humphrey2#wilkins.com'
)
);
If the second is returned, I can do a simple foreach($array as $key => $person), but if there is only one result returned (the first example), I can't run a foreach on this as I need to access like: $person['name'] within the foreach loop.
Is there any way to make the one result believe its a multidimensional array?
Try this :
if(!is_array($array[0])) {
$new_array[] = $array;
$array = $new_array;
}
I would highly recommended making your data's structure the same regardless of how many elements are returned. It will help log terms and this will have to be done anywhere that function is called which seems like a waste.
You can check if a key exists and do some logic based on that condition.
if(array_key_exists("name", $array){
//There is one result
$array['name']; //...
} else {
//More then one
foreach($array as $k => $v){
//Do logic
}
}
You will have the keys in the first instance in the second yours keys would be the index.
Based on this, try:
function isAssoc(array $arr)
{
if (array() === $arr) return false;
return array_keys($arr) !== range(0, count($arr) - 1);
}
if(isAssoc($array)){
$array[] = $array;
}
First check if the array key 'name' exists in the given array.
If it does, then it isn't a multi-dimensional array.
Here's how you can make it multi-dimensional:
if(array_key_exists("name",$array))
{
$array = array($array);
}
Now you can loop through the array assuming it's a multidimensional array.
foreach($array as $key => $person)
{
$name = $person['name'];
echo $name;
}
The reason of this is probably because you use either fetch() or fetchAll() on your db. Anyway there are solutions that uses some tricks like:
$arr = !is_array($arr[0]) ? $arr : $arr[0];
or
is_array($arr[0]) && ($arr = $arr[0]);
but there is other option with array_walk_recursive()
$array = array(
array(
'name' => 'Humphrey1',
'email' => 'humphrey1#wilkins.com'
),
array(
'name' => 'Humphrey2',
'email' => 'humphrey2#wilkins.com'
)
);
$array2 = array(
'name' => 'Humphrey2',
'email' => 'humphrey2#wilkins.com'
);
$print = function ($item, $key) {
echo $key . $item .'<br>';
};
array_walk_recursive($array, $print);
array_walk_recursive($array2, $print);

Merge array with varying key value pairs

So I have various arrays which do not always have the same key/value pairs in them. What I want to do is to be able to merge the arrays, but to add in empty key/value pairs if they don't already exist in that array, but do in others. It's hard to explain but this might explain it better:
$arrayOne = array('name' => 'rory', 'car' => 'opel');
$arrayTwo = array('name' => 'john', 'dog' => 'albert');
I need to somehow turn this into:
$finalArray = array(
array('name' => 'rory', 'car' => 'opel', 'dog' => ''),
array('name' => 'john', 'car' => '', 'dog' => 'albert')
);
I have been looking through PHP's documentation but can't find anything that will do this for me. Can anyone point me in the right direction? I don't even know an appropriate search term for what I want to achieve here, "array merge" isn't specific enough.
<?php
$arrayOne = array('name' => 'rory', 'car' => 'opel');
$arrayTwo = array('name' => 'john', 'dog' => 'albert');
$diff1=array_diff(array_flip($arrayOne), array_flip($arrayTwo));
$diff2=array_diff(array_flip($arrayTwo), array_flip($arrayOne));
//array_flip flips the key of array with value
//array_diff would return the values in the first array that are not present in any of the other arrays inside
foreach ($diff2 as $s) {
$arrayOne[$s]="";
}
foreach ($diff1 as $s) {
$arrayTwo[$s]="";
};
//set key that didn't exist in that array as ""
$finalArray[]=$arrayOne;
$finalArray[]=$arrayTwo;
//add the arrays to the final array
print_r($finalArray);
Here's what I would do:
Merge your separate arrays into one (into a temporary var) using array_merge
Get the unique keys of this new array using array_keys
For each separate array, loop through the new keys array and add an empty value for each key that is not in the array. Then push the separate array into a final array.
<?php
$arrayOne = array('name' => 'rory', 'car' => 'opel');
$arrayTwo = array('name' => 'john', 'dog' => 'albert');
$new = array_merge($arrayOne,$arrayTwo);
$new = array_keys($new);
$newarray = array();
foreach($new as $value){
$newarray[0][$value] = isset($arrayOne[$value]) ? $arrayOne[$value] : '' ;
$newarray[1][$value] = isset($arrayTwo[$value]) ? $arrayTwo[$value] : '' ;
}
echo "<pre>";print_r($newarray);
You can also use this short answer
$arrayOne = array('name' => 'rory', 'car' => 'opel');
$arrayTwo = array('name' => 'john', 'dog' => 'albert');
$defaults = array('name' => '','car' => '','dog' => '');
$arrayOne += $defaults;
$arrayTwo += $defaults;
$newarray = array($arrayOne,$arrayTwo);
echo "<pre>";print_r($newarray);
Basing on what Justin Powell outlined, I managed to come up with this code before the other two code examples were posted (thank you mamta & user6439245).
I also needed to take the keys containing numbers and sort them appropriately, otherwise my keys would've been indexed like employer_1, education_1, employer_2, education_2.
// get the initial form entries data
$entries = array(
array('name' => 'john', 'car' => 'fiat', 'employer_1' => 'tangerine', 'education_1' => 'hideaways', 'education_2' => 'extras'),
array('name' => 'rory', 'car' => 'opel', 'employer_1' => 'sagittarius', 'employer_2' => 'tangerine', 'employer_3' => 'thehideout', 'education_1' => 'knatchbull')
);
// create an empty array to populate with all field keys
$mergedKeys = array();
// push all field keys into the array
foreach($entries as $entry){
foreach($entry as $key => $value){
array_push($mergedKeys, $key);
}
}
// remove duplicate keys from the array
$uniqueMergedKeys = array_unique($mergedKeys);
// create a new array to populate with the field keys we need to sort - the ones with numbers in
$keysToSort = array();
// push the number-containing keys into the array
$i=0;
foreach($uniqueMergedKeys as $uniqueKey){
if(1 === preg_match('~[0-9]~', $uniqueKey)){
array_push($keysToSort, $uniqueKey);
}
$i++;
}
// remove the number containing keys from the unique keys array
$uniqueMergedKeys = array_diff($uniqueMergedKeys, $keysToSort);
// sort the keys that need sorting
sort($keysToSort);
// put the newly sorted keys back onto the original keys array
foreach($keysToSort as $key){
array_push($uniqueMergedKeys, $key);
}
$final = array();
$i = 0;
foreach($entries as $entry){
foreach($uniqueMergedKeys as $key){
//if($entries[$i][$key]){
if (array_key_exists($key, $entries[$i])) {
$final[$i][$key] = $entries[$i][$key];
} else {
$final[$i][$key] = '';
}
}
$i++;
}
echo '<pre>'; print_r($final); echo '</pre>';

php remove object from array of objects

I'm trying to remove an object from an array of objects by its' index. Here's what I've got so far, but i'm stumped.
$index = 2;
$objectarray = array(
0=>array('label'=>'foo', 'value'=>'n23'),
1=>array('label'=>'bar', 'value'=>'2n13'),
2=>array('label'=>'foobar', 'value'=>'n2314'),
3=>array('label'=>'barfoo', 'value'=>'03n23')
);
//I've tried the following but it removes the entire array.
foreach ($objectarray as $key => $object) {
if ($key == $index) {
array_splice($object, $key, 1);
//unset($object[$key]); also removes entire array.
}
}
Any help would be appreciated.
Updated Solution
array_splice($objectarray, $index, 1); //array_splice accepts 3 parameters
//(array, start, length) removes the given array and then normalizes the index
//OR
unset($objectarray[$index]); //removes the array at given index
$reindex = array_values($objectarray); //normalize index
$objectarray = $reindex; //update variable
array_splice($objectarray, $index, 1);
//array_splice accepts 3 parameters (array, start, length) and removes the given
//array and then normalizes the index
//OR
unset($objectarray[$index]); //removes the array at given index
$reindex = array_values($objectarray); //normalize index
$objectarray = $reindex; //update variable
You have to use the function unset on your array.
So its like that:
<?php
$index = 2;
$objectarray = array(
0 => array('label' => 'foo', 'value' => 'n23'),
1 => array('label' => 'bar', 'value' => '2n13'),
2 => array('label' => 'foobar', 'value' => 'n2314'),
3 => array('label' => 'barfoo', 'value' => '03n23')
);
var_dump($objectarray);
foreach ($objectarray as $key => $object) {
if ($key == $index) {
unset($objectarray[$index]);
}
}
var_dump($objectarray);
?>
Remember, your array will have odd indexes after that and you must (if you want) reindex it.
$foo2 = array_values($objectarray);
in that case you won't need that foreach just unset directly
unset($objectarray[$index]);

How to extract an array that has a given structure and which's key => value matches a given value of an mutlidimensional array?

I have an array consisting of many other arrays, which might also consist of other arrays. Its basically like a navigation hierarchy, one menu link can be a menu with sub menus and so on.
The structure of $mainarray is like this:
'childarray1' => array(
'link' => array(
..
'mykey' => 'valueofinterest'
),
'below' => array() of childarrays
),
'childarray2' => array(
'link' => array(
..
'mykey' => 'somevalue'
)
),
'childarray3' => array(
'link' => array(
..
'mykey' => 'someothervalue'
),
'below' => array() of childarrays
)
Each childarray can have 2 direct child keys, 'links' and optionally 'below'. Within links there is always a key 'mykey', which is the only key that I need to check. If a child array has ['links']['mykey'] == 'valueofinterest', I'd like to have this element returned, like $sub = $mainarray['child1']['below']['child11']['below']['childofinterest'].
'below' means that the childarray has childs itself which can also have below arrays (sub menu..).
My hude problem is that the childarray I try to find can be in any other childarrays'S 'below' key, I dont know the depth (its not too deep, though it can vary). I've tried to mess with foreach loops and while loops and combining those, I just cant figure it out how to get the child array. I want to do it like this:
$value = 'xxx';
$sub = return_sub_menu($value);
function return_sub_menu($value) {
$array = $mainarray();
$sub = array();
// find the child array which's ['link']['mykey'] == $value;
// $sub is now something like:
// 'childarray321' => array(
// 'link' => array(
// ..
// 'mykey' => 'xxx'
// ),
// 'below' => array() of childarrays which i NEEED :)
//
// )
return $sub;
}
I've tried to walk recursively but cant figure out how to return the element :(
function recursiveSearch($array, $value){
foreach($array as $sub){
if ($sub['link']['mykey'] == $value)
return $sub ;
if (!empty($sub['below'])){
$returned = recursiveSearch($sub['below'], $value);
if ($returned !== null)
return $returned ;
}
}
return null ;
}
$sub = recursiveSearch($array, "valueofinterest");
//Returns array with ['link']['mykey'] == $value ;
var_dump($sub);
UPDATE V2
Fixed the function, so it works now
Try like this,
if (array_key_exists('keyvalue', $array)) {
$subarray = $array['keyvalue'];
return $subarray;
}
It will return sub array
here it is.
$finalarray = array_map(create_function('$yourarray', 'return $yourarray["arrayindex"];'), $actualarray );

Extract array parts based on given keys in array

I have two arrays. One containing the data and other contains the keys. So I have
$data = array(
'name' => array('label' => 'Name:', 'value' => 'Genghis'),
'age' => array('label' => 'Age:', 'value' => '67'),
'weigh' => array('label' => 'Weigh in Kgs:', 'value' => '78')
);
and
$keys = array('name', 'age');
Now I want to extract only the name and age elements of $data. Some thing like this.
$extracted = somemethod($data, $keys);
var_export($extracted);
Output should be like this.
array(
'name' => array(
'label' => 'Name:',
'value' => 'Genghis',
),
'age' => array(
'label' => 'Age:',
'value' => '67',
),
)
How can i do this?
I would use an array_intersect_key() function like this:
$data = array(...); // initial array as described
$retained_keys = array('name' => 'value not used', 'age' => 'value not used');
$filtered_array = array_intersect_key($data, $retained_keys);
Loop over the keys, grab the array values, and return them:
function somemethod($data, $keys) {
$return = array();
foreach( $keys as $k) {
$return[$k] = isset( $data[$k]) ? $data[$k] : null;
}
return $return;
}
The above adds 'null' when a field isn't found. You can modify the foreach loop to just skip the key when it's not found in the $data array, like this:
function somemethod($data, $keys) {
$return = array();
foreach( $keys as $k) {
if( isset( $data[$k])) {
$return[$k] = $data[$k];
}
}
return $return;
}
Edit: To extend on Mike Brant's answer, array_intersect_key() can be used with array_flip() in a function to achieve the desired output:
function somemethod($data, $keys) {
$keys = array_flip( $keys);
return array_intersect_key($data, $keys);
}
Yes, it uses array_flip(), but the original $keys array is left unmodified, as a copy of that array is what gets flipped. So, you would still call this function with:
$extracted = somemethod( $data, array('name', 'age'));
Not exactly onerous to write
$extracted = array();
foreach($keys as $key) {
if (isset($data[$key]))
$extracted[$key] = $data[$key];
}

Categories