PHP push values into associative array - php

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')]
);

Related

Change $key of associative array in a foreach loop in php

I have an array like this:
array(
'firstName' => 'Joe',
'lastName' => 'Smith'
)
I need to loop over every element in my array and in the end, the array should look like this:
array(
'FirstName' => 'Joe',
'LastName' => 'Smith'
)
Failed idea was:
foreach($array as $key => $value)
{
$key = ucfirst($key);
}
This obviously will not work, because the array is not passed by reference. However, all these attempts also fail:
foreach(&$array as $key => $value)
{
$key = ucfirst($key);
}
foreach($array as &$key => $value)
{
$key = ucfirst($key);
}
Pretty much at my wits end with this one. I'm using Magento 1.9.0.1 CE, but that's pretty irrelevant for this problem. If you must know, the reason I have to do this is because I have a bunch of object that's I'm returning as an array to be assembled into a SOAP client. The API I'm using requires the keys to begin with a capital letter...however, I don't wish to capitalize the first letter of my object's variable names. Silly, I know, but we all answer to someone, and that someone wants it that way.
unset it first in case it is already in the proper format, otherwise you will remove what you just defined:
foreach($array as $key => $value)
{
unset($array[$key]);
$array[ucfirst($key)] = $value;
}
You can't modify the keys in a foreach, so you would need to unset the old one and create a new one. Here is another way:
$array = array_combine(array_map('ucfirst', array_keys($array)), $array);
Get the keys using array_keys
Apply ucfirst to the keys using array_map
Combine the new keys with the values using array_combine
The answers here are dangerous, in the event that the key isn't changed, the element is actually deleted from the array. Also, you could unknowingly overwrite an element that was already there.
You'll want to do some checks first:
foreach($array as $key => $value)
{
$newKey = ucfirst($key);
// does this key already exist in the array?
if(isset($array[$newKey])){
// yes, skip this to avoid overwritting an array element!
continue;
}
// Is the new key different from the old key?
if($key === $newKey){
// no, skip this since the key was already what we wanted.
continue;
}
$array[$newKey] = $value;
unset($array[$key]);
}
Of course, you'll probably want to combine these "if" statements with an "or" if you don't need to handle these situations differently.
This might work:
foreach($array as $key => $value) {
$newkey = ucfirst($key);
$array[$newkey] = $value;
unset($array[$key]);
}
but it is very risky to modify an array like this while you're looping on it. You might be better off to store the unsettable keys in another array, then have a separate loop to remove them from the original array.
And of course, this doesn't check for possible collisions in the aray, e.g. firstname -> FirstName, where FirstName already existed elsewhere in the array.
But in the end, it boils down to the fact that you can't "rename" a key. You can create a new one and delete the original, but you can't in-place modify the key, because the key IS the key to lookup an entry in the aray. changing the key's value necessarily changes what that key is pointing at.
Top of my head...
foreach($array as $key => $value){
$newKey = ucfirst($key);
$array[$newKey] = $value;
unset($array[$key]);
}
Slightly change your way of thinking. Instead of modifying an existing element, create a new one, and remove the old one.
If you use laravel or have Illuminate\Support somewhere in your dependencies, here's a chainable way:
>>> collect($array)
->keys()
->map(function ($key) {
return ucfirst($key);
})
->combine($array);
=> Illuminate\Support\Collection {#1389
all: [
"FirstName" => "Joe",
"LastName" => "Smith",
],
}

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.)

Unset multiple intems in array

Is there a PHP built-in function to unset multiple array items by key?
That would be a native equivalent of:
foreach($badElements as $k) {
unset($allElements[$k]);
}
or, even better:
$keys = array_keys($badElements);
foreach($keys as $k) {
unset($allElements[$k]);
}
The following doesn't fullfill your requirement in complete since it's not in-situ. But maybe you're ok with copying the array:
$v = array("lol"=>"blub", "lal"=>"blab", "lulz"=>"gagh");
$k = array("lol", "lulz");
var_dump(array_diff_key($v, array_flip($k)));
[ run it on codepad ]
You could create an array of the keys you want to remove and loop through, explicitly unsetting them.
Examples:
$removeKeys = array('name', 'email');
foreach($removeKeys as $key) {
unset($badElements[$key]);
}
Or you could point the variable to a new array that has the keys removed.
$badElements = array_diff_key($badElements, array_flip($removeKeys));
or pass all of the array members to unset().
unset($badElements['name'], $badElements['email'])

PHP Array Combination Best Method

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.

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