PHP Array Combination Best Method - php

given the following arrays in php, how can i best merge them together
$masterkeys = array('Key1','Key2');
$settings_foo = array(
array('ID'=>'Key1',
'Foo_Setting'=>'SomeValue'));
$settings_bar = array(
array('ID'=>'Key1',
'Bar_Setting'=>'SomeOtherValue'));
in the end I need $masterkeys to be the combination of each of the settings_[foo|bar] arrays.
Array( ['Key1'] = Array('Foo_Setting'=>'SomeValue','Bar_Setting'=>'SomeOtherValue') );
I do know I can use a couple foreach loops on this, but just wondering if there are a couple PHP array functions that can splice them together.

While you can use some of PHP's array functions, your input data isn't in a very nice format. You'll have the fewest iterations (and probably best performance) by writing them yourself:
# create an array of $masterkey => array()
$result = array_combine($masterkeys, array_fill(0, count($masterkeys), array()));
# loop through each settings array
foreach (array($settings_foo, $settings_bar) as $settings)
{
foreach ($settings as $s)
{
# merge the array only if the ID is in the master list
$key = $s['ID'];
if (array_key_exists($key, $result))
$result[$key] = array_merge($result[$key], $s);
}
}
# unset all extraneous 'ID' properties
foreach (array_keys($result) as $i)
unset($result[$i]['ID']);
var_dump($result);
As an alternative, you could look into array_map and array_filter, but due to the way the data is structured, I'm not sure they'll be of much use.

I'm not sure how your $masterkeys array plays in here, but array_merge_recursive may do what you want.

Related

Change array keys to lowercase

I'm looking for a nifty php solution to replace a standard forloop. i dont care at all about the inner workings of my normalize method.
Here is my code:
$pairs=[];
foreach($items as $key => $val){
$key = $this->normalizeKey($key);
$pairs[$key] = $val;
}
private function normalizeKey($key)
{
// lowercase string
$key = strtolower($key);
// return normalized key
return $key;
}
I'd like to learn the PHP language a bit better. I thought array_walk would be nice to use, but that operates on the values and not the keys.
I am looking for a PHP array method that can perform this code instead of a foreach loop.
You want array_change_key_case
$pairs = array_change_key_case($items);
Just for fun, though it requires three functions. You can replace strtolower() with whatever since this can already be done with array_change_key_case():
$pairs = array_combine(array_map('strtolower', array_keys($items)), $items);
Get the keys from $items
Map the array of keys to strtolower()
Combine the new keys with $items values
You can also use an anonymous function as the callback if you need something more complex. This will append -something to each key:
$pairs = array_combine(array_map(function ($v) {
return $v . '-something';
},
array_keys($items)), $items);
You can normalise the keys and store them and their corresponding values in a temporary array and assign it to your original $pairs array.
Like so:
$normalised = [];
foreach($pairs as $key => $value) {
$normalised[$this->normalizeKey($key)] = $value;
};
$pairs = $normalised;
Edit 2022: Or better yet, use #Sherif's answer as it uses a standand library function

Convert array elements into string without traversing array

Consider the following array-
$array = array("index1"=>"8787",
"index2"=>909,
"index3"=>"234234",
"index4"=>"00-00-0000",
"index5"=>"false",
"index6"=>"5432",
"index7"=>2834,
"index8"=>42847628
);
Is there a way to convert the non-string elements of the array into string type without actually traversing the array .
The array could be quite big as it is created dynamically and will affect the response time.
I could use the following
foreach ($array as $key => $value) {
$array[$key] = (gettype($value)=="string")?$value:(string)$value;
}
However,is there any better way?
You can doo this only by traversing. So, in such way using array_map:
$array = array("index1"=>"8787",
"index2"=>909,
"index3"=>"234234",
"index4"=>"00-00-0000",
"index5"=>"false",
"index6"=>"5432",
"index7"=>2834,
"index8"=>42847628
);
$result = array_map('strval',$array );
var_dump($result);
There are many solutions. You can also do it from within the foreach loop:
foreach ($array as $key => &$_value) {
$_value = strval($_value);
}
The & is important here. (The _ is just a convention I use to prevent me from mixing reference and non-reference variables.)

PHP push values into associative array

I can't find an answer to this anywhere.
foreach ($multiarr as $array) {
foreach ($array as $key=>$val) {
$newarray[$key] = $val;
}
}
say $key has duplicate names, so when I am trying to push into $newarray it actually looks like this:
$newarray['Fruit'] = 'Apples';
$newarray['Fruit'] = 'Bananas';
$newarray['Fruit'] = 'Oranges';
The problem is, the above example just replaces the old value, instead of pushing into it.
Is it possible to push values like this?
Yes, notice the new pair of square brackets:
foreach ($multiarr as $array) {
foreach ($array as $key=>$val) {
$newarray[$key][] = $val;
}
}
You may also use array_push(), introducing a bit of overhead, but I'd stick with the shorthand most of the time.
I'll offer an alternative to moonwave99's answer and explain how it is subtly different.
The following technique unpacks the indexed array of associative arrays and serves each subarray as a separate parameter to array_merge_recursive() which performs the merging "magic".
Code: (Demo)
$multiarr = [
['Fruit' => 'Apples'],
['Fruit' => 'Bananas'],
['Fruit' => 'Oranges'],
['Veg' => 'Carrot'],
//['Veg' => 'Leek'],
];
var_export(
array_merge_recursive(...$multiarr)
);
As you recursively merge, if there is only one value for a respective key, then a subarray is not used, if there are multiple values for a key, then a subarray is used.
See this action by uncommenting the Leek element.
p.s. If you know that you are only targetting a single column of data and you know the key that you are targetting, then array_column() would be a wise choice.
Code: (Demo)
var_export(
['Fruit' => array_column($multiarr, 'Fruit')]
);

Split a string to form multidimensional array keys?

I'm creating JSON encoded data from PHP arrays that can be two or three levels deep, that look something like this:
[grandParent] => Array (
[parent] => Array (
[child] => myValue
)
)
The method I have, which is simply to create the nested array manually in the code requires me to use my 'setOption' function (which handles the encoding later) by typing out some horrible nested arrays, however:
$option = setOption("grandParent",array("parent"=>array("child"=>"myValue")));
I wanted to be able to get the same result by using similar notation to javascript in this instance, because I'm going to be setting many options in many pages and the above just isn't very readable, especially when the nested arrays contain multiple keys - whereas being able to do this would make much more sense:
$option = setOption("grandParent.parent.child","myValue");
Can anyone suggest a way to be able to create the multidimensional array by splitting the string on the '.' so that I can json_encode() it into a nested object?
(the setOption function purpose is to collect all of the options together into one large, nested PHP array before encoding them all in one go later, so that's where the solution would go)
EDIT: I realise I could do this in the code:
$options['grandparent']['parent']['child'] = "myValue1";
$options['grandparent']['parent']['child2'] = "myValue2";
$options['grandparent']['parent']['child3'] = "myValue3";
Which may be simpler; but a suggestion would still rock (as i'm using it as part of a wider object, so its $obj->setOption(key,value);
This ought to populate the sub-arrays for you if they haven't already been created and set keys accordingly (codepad here):
function set_opt(&$array_ptr, $key, $value) {
$keys = explode('.', $key);
// extract the last key
$last_key = array_pop($keys);
// walk/build the array to the specified key
while ($arr_key = array_shift($keys)) {
if (!array_key_exists($arr_key, $array_ptr)) {
$array_ptr[$arr_key] = array();
}
$array_ptr = &$array_ptr[$arr_key];
}
// set the final key
$array_ptr[$last_key] = $value;
}
Call it like so:
$opt_array = array();
$key = 'grandParent.parent.child';
set_opt($opt_array, $key, 'foobar');
print_r($opt_array);
In keeping with your edits, you'll probably want to adapt this to use an array within your class...but hopefully this provides a place to start!
What about $option = setOption("grandParent", { parent:{ child:"myValue" } });?
Doing $options['grandparent']['parent']['child'] will produce an error if $options['grandparent']['parent'] was not set before.
The OO version of the accepted answer (http://codepad.org/t7KdNMwV)
$object = new myClass();
$object->setOption("mySetting.mySettingsChild.mySettingsGrandChild","foobar");
echo "<pre>".print_r($object->options,true)."</pre>";
class myClass {
function __construct() {
$this->setOption("grandparent.parent.child","someDefault");
}
function _setOption(&$array_ptr, $key, $value) {
$keys = explode('.', $key);
$last_key = array_pop($keys);
while ($arr_key = array_shift($keys)) {
if (!array_key_exists($arr_key, $array_ptr)) {
$array_ptr[$arr_key] = array();
}
$array_ptr = &$array_ptr[$arr_key];
}
$array_ptr[$last_key] = $value;
}
function setOption($key,$value) {
if (!isset($this->options)) {
$this->options = array();
}
$this->_setOption($this->options, $key, $value);
return true;
}
}
#rjz solution helped me out, tho i needed to create a array from set of keys stored in array but when it came to numerical indexes, it didnt work. For those who need to create a nested array from set of array indexes stores in array as here:
$keys = array(
'variable_data',
'0',
'var_type'
);
You'll find the solution here: Php array from set of keys

PHP key value pairs vs. arrays

I'm trying to pass key values pairs within PHP:
// "initialize"
private $variables;
// append
$this->variables[] = array ( $key = $value)
// parse
foreach ( $variables as $key => $value ) {
//..
}
But it seems that new arrays are added instead of appending the key/value, nor does the iteration work as expect. Please let me know what the proper way is.
Solution
$this->variables[$key] = $value;
did the trick - the iteration worked as described above.
I think you may be looking for:
$this->variables[$key] = $value;
The way you have it right now you are creating an array of arrays, so you would have to do this:
foreach($this->variables as $tuple) {
list($key, $value) = $tuple;
}
Referring to Perl, but helps understand the difference between hashes and arrays:
Some people think that hashes are like arrays (the old name 'associative array' also indicates this, and in some other languages, such as PHP, there is no difference between arrays and hashes.), but there are two major differences between arrays and hashes. Arrays are ordered, and you access an element of an array using its numerical index. Hashes are un-ordered and you access a value using a key which is a string.
Source: http://perlmaven.com/perl-hashes

Categories