sadly i havent found any solution yet.
I have an multidimensional array which looks like this:
Array
(
[0] => Array
(
[Symbol] => CASY.US
[Position] => 169873920
)
[1] => Array
(
[Symbol] => US500
[Position] => 168037428
) )
Now i want to write the name of the keys of the inner array into variables so that i have these variables with the values:
$col1 = "Symbol"
$col2 = "Position"
How can i achieve that? Somehow with a couple of foreach loops?
Background: After that i want to check if the columns have the right name for a validation.
Thanks in advance!
Loop nested and save the keys to an array with "col" and an integer that you later can (if you really must extract), but I recommend to keep them in the array.
foreach($array as $subarray){
$i = 1;
foreach($subarray as $key => $val){
$keys["col" . $i] = $key;
$i++;
}
break; // no need to keep looping if the array is uniform
}
//if you must:
extract($keys);
https://3v4l.org/ALVtp
If the subarrays are not the same then you need to loop all subarrays and see if the key has already been saved, if not save it else skip it.
$keys =[];
$i = 1;
foreach($array as $subarray){
foreach($subarray as $key => $val){
if(!in_array($key, $keys)){
$keys["col" . $i] = $key;
$i++;
}
}
}
var_dump($keys);
//if you must:
extract($keys);
var_dump($col1, $col2, $col3);
https://3v4l.org/EklPK
Honestly I would do something like this:
$required = array_flip(['Symbol', 'Position']); //flip because I am lazy like that ['Symbol'=>0, 'Position'=>1]
foreach($array as $subarray){
$diff = array_diff_key($required, $subarray);
//prints any keys in $required that are not in $subarray
print_r($diff);
if(!empty($diff)){
//some required keys were missed
}
}
While its not clear how you validate these the reason is as I explained in this comment
it still doesn't solve the problem, as you really have no way to know what the keys will be (if they are not uniform). So with my example foo is $col3 what if I have bar later that's $col4 what if the order is different next time.... they will be different numbers. Sure it's a few what if's but you have no guarantees here.
By dynamically numbering the keys, if the structure of the array ever changes you would have no idea what those dynamic variables contain, and as such no idea how to validate them.
So even if you manage to make this work, if your data ever changes you going to have to re-visit the code.
In any case if your wanting to see if each array contains the keys it needs to, what I put above would be a more sane way to do it.
Related
I was using combine_array to update a MySQL table from a CSV file. I thought everything was working like a champ, but it turns out the data source isn't amazing. There are multiple columns with the same name and those columns become the keys in an array. Example take the two arrays:
array 1
[0]=>"name"
[1]=>"email"
[2]=>"shoe size"
[3]=>"email"
array 2
[0]=>"Jake Doe"
[1]=>"jake#example.mail"
[2]=>"10.5"
[3]=>""
if I was to use array_combine($array1,$array2) I would get:
["name"]=>"Jake Doe"
["email"]=>""
["shoe size"]=>"10.5"
The problem is that I'd obviously prefer to have the email not get overwritten by a blank value. What I can up with is the function below. What I'm looking for is just a second set of eyes. Is this there a better way to do this? I hate that I have two nested ifs, but I'm not sure how I'd go about making it cleaner or if that's even possible.
//array_combine simply overwrites repeat keys, this only overwrites if the value is empty
//if the first instance of the key has a value, it ignores duplicate keys
function new_array_combine($key_array,$value_array){
foreach($value_array as $key=>$value){
if(array_key_exists($key_array[$key],$new_array)){
if(empty($new_array[$key_array[$key]]))$new_array[$key_array[$key]]=$value;
}else{
$new_array[$key_array[$key]]=$value;
}
}
return $new_array;
}
The only problem I see with your program is when key names do not match in each array
array 1
[0]=>"name"
[1]=>"email"
[2]=>"shoe size"
[3]=>"email"
array 2
[0]=>"Jake Doe"
[1]=>"jake#example.mail"
[3]=>"10.5"
[4]=>""
Suggested modifications:
function new_array_combine($a1, $a2){
$result=Array();
reset($a1);
foreach($a2 as &$v){
$key=current($a1);
if (!isset($result[$key])||empty($result[$key]))
$result[$key]=$v;
next($a1);
}
return $result;
}
Blah. Trying to rescue this response, since my first obviously missed the entire point of the post.
If you're only worried about those blank values, then I would say you could walk the arrays once through first, 'cleaning' them by deleting indexes with no corresponding value:
<?php
// $a and $b as defined in the example
foreach($a as $k => $v) {
if(empty($b[$k])) {
unset($a[$k]);
unset($b[$k]);
}
}
$c = array_combine($a, $b);
print_r($c);
Output:
Array(
[name] => Jake Doe
[email] => jake#example.mail
[shoesize] => 10.5
)
Edit: To include blank values (but still not let blanks override existing values), first get the unique keys from $a and use it to build an empty result array, then just skip blank values while looping through...
<?php
// $a and $b as defined in the example
$result = array();
$keys = array_unique($a);
foreach($keys as $key) $result[$key] = '';
foreach($a as $k => $v) {
if(empty($b[$k])) continue;
$result[$v] = $b[$k];
}
print_r($result);
Output:
Array(
[name] => Jake Doe
[email] => jake#example.mail
[shoesize] => 10.5
)
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",
],
}
I have an array of dictionnaries like:
$arr = array(
array(
'id' => '1',
'name' => 'machin',
),
array(
'id' => '2',
'name' => 'chouette',
),
);
How can I find the name of the array containing the id 2 (chouette) ?
Am I forced to reindex the array ?
Thank you all, aparently I'm forced to loop through the array (what I wanted to avoid), I thought that it were some lookup fonctions like Python. So I think I'll reindex with id.
Just find the index of array that contains the id you want to find.
SO has enough questions and answers on this topic available.
Assuming you have a big array with lots of data in your real application, it might be too slow (for your taste). In this case, you indeed need to modify the structure of your arrays, so you can look it up faster, e.g. by using the id as an index for the name (if you are only interested in the name).
As a for loop would be the best way to do this, I would suggest changing you array so that the id is the arrays index. For example:
$arr = array(
1 => 'machin',
2 => 'chouette',
);
This way you could just get the name for calling $arr[2]. No looping and keeping your program running in linear time.
$name;
foreach ($arr as $value){
if ( $value['id'] == 2 ){
$name = $value['name'];
break;
}
}
I would say that it might be very helpful to reindex the information. If the ID is unique try something like this:
$newarr = array();
for($i = 0;$i < count($arr);$i++){ $newarr[$arr[$i]['id']] = $arr[$i]['name']; }
The result would be:
$newarr = array('1'=>'machin','2'=>'chouette');
Then you can go trough the array with "foreach" like this:
foreach($newarr as $key => $value){
if($value == "machin"){
return $key;
}
}
But of course the same would work with your old array:
foreach($arr as $item){
if($item['name'] == "machin"){
return $item['id'];
}
}
It depends on what you are planning to do with the array ;-)
array_key_exist() is the function to check for keys. foreach will help you get down in the multidimensional array. This function will help you get the name element of an array and let you specify a different id value.
function findKey($bigArray, $idxVal) {
foreach($bigArray as $array) {
if(array_key_exists('id', $array) && $array['id'] == $idxVal) {
return $array['name'];
}
}
return false;
}
//Supply your array for $arr
print(findKey($arr, '2')); //"chouette"
It's a bit crude, but this would get you the name...
$name = false;
foreach($arr as $v) {
if($v['id'] == '2') {
$name = $v['name'];
break;
}
}
echo $name;
So no, you are not forced to reindex the array, but it would make things easier.
I have a PHP array that looks like that:
$array = Array
(
[teamA] => Array
(
[188555] => 1
)
[teamB] => Array
(
[188560] => 0
)
[status] => Array
(
[0] => on
)
)
In the above example I can use the following code:
echo $array[teamA][188555];
to get the value 1.
The question now, is there a way to get the 188555 in similar way;
The keys teamA, teamB and status are always the same in the array. Alse both teamA and teamB arrays hold always only one record.
So is there a way to get only the key of the first element of the array teamA and teamB?
More simple:
echo key($array['teamA']);
More info
foreach($array as $key=>$value)
{
foreach($value as $k=>$v)
{
echo $k;
}
}
OR use key
echo key($array['teamA']);
echo array_keys($array['teamA'])[0];
Refer this for detailed information from official PHP site.
Use two foreach
foreach($array as $key => $value){
foreach($value as $key1 => $value2){
echo $key1;
}
}
This way, you can scale your application for future use also. If there will be more elements then also it would not break application.
You can use array_flip to exchange keys and values. So array('12345' => 'foo') becomes array('foo' => '12345').
Details about array_flip can be studied here.
I would suggest using list($key, $value) = each($array['teamA']) since the question was for both key and value. You won't be able to get the second or third value of the array without a loop though. You may have to reset the array first if you have changed its iterator in some way.
I suppose the simplest way to do this would be to use array_keys()?
So you'd do:
$teamAKey = array_shift(array_keys($array['TeamA']));
$teamBKey = array_shift(array_keys($array['TeamB']));
Obviously your approach would depend on how many times you intend to do it.
More info about array_keys and array_shift.
Im trying to add a key=>value to a existing array with a specific value.
Im basically looping through a associative array and i want to add a key=>value foreach array that has a specific id:
ex:
[0] => Array
(
[id] => 1
[blah] => value2
)
[1] => Array
(
[id] => 1
[blah] => value2
)
I want to do it so that while
foreach ($array as $arr) {
while $arr['id']==$some_id {
$array['new_key'] .=$some value
then do a array_push
}
}
so $some_value is going to be associated with the specific id.
The while loop doesn't make sense since keys are unique in an associative array. Also, are you sure you want to modify the array while you are looping through it? That may cause problems. Try this:
$tmp = new array();
foreach ($array as $arr) {
if($array['id']==$some_id) {
$tmp['new_key'] = $some_value;
}
}
array_merge($array,$tmp);
A more efficient way is this:
if(in_array($some_id,$array){
$array['new_key'] = $some_value;
}
or if its a key in the array you want to match and not the value...
if(array_key_exists($some_id,$array){
$array['new_key'] = $some_value;
}
When you use:
foreach($array as $arr){
...
}
... the $arr variable is a local copy that is only scoped to that foreach. Anything you add to it will not affect the $array variable. However, if you call $arr by reference:
foreach($array as &$arr){ // notice the &
...
}
... now if you add a new key to that array it will affect the $array through which you are looping.
I hope I understood your question correctly.
If i understood you correctly, this will be the solution:
foreach ($array as $arr) {
if ($arr['id'] == $some_id) {
$arr[] = $some value;
// or: $arr['key'] but when 'key' already exists it will be overwritten
}
}