I want to create and initialize a multidimensional array with known possible keys for the second dimension but no values.
This array will store event_ids (populated dynamically) and for each event_id an array having exactly four different counts (also filled dynamically).
Structure I want to create
Array
(
[0] => Array =================> This index will be the event_id
(
[invitation_not_sent_count] =>
[no_response_yet_count] =>
[will_not_attend_count] =>
[will_attend_count] =>
)
)
What I did so far?
$DataArray = array();
$DataArray[] = array('invitation_not_sent_count' => '',
'no_response_yet_count' => '',
'will_not_attend_count' => '',
'will_attend_count' => '');
And inside the loop I am populating data dynamically like:
$DataArray[$result->getId()]['no_response_yet_count'] = $NRCount;
What I get is:
Array
(
[0] => Array
(
[invitation_not_sent_count] =>
[no_response_yet_count] =>
[will_not_attend_count] =>
[will_attend_count] =>
)
[18569] => Array
(
[no_response_yet_count] => 2
)
[18571] => Array
(
[no_response_yet_count] => 1
)
)
What I want is that if a value is not available in the iteration, its entry should be empty as defined at initialization time. So if all other counts are empty in the data except no_response_yet_count, the array should be:
Expected Output
Array
(
[18569] => Array
(
[invitation_not_sent_count] =>
[no_response_yet_count] => 2
[will_not_attend_count] =>
[will_attend_count] =>
)
[18571] => Array
(
[invitation_not_sent_count] =>
[no_response_yet_count] => 1
[will_not_attend_count] =>
[will_attend_count] =>
)
)
I usually resort to a mapping function at that point:
function pre_map(&$row) {
$row = array
(
'invitation_not_sent_count' => '',
'no_response_yet_count' => '',
'will_not_attend_count' => '',
'will_attend_count' => ''
);
}
Then in the while/for loops:
{
$id = $result->getId();
if (!isset($DataArray[$id])) { pre_map($DataArray[$id]); }
$DataArray[$id]['no_response_yet_count'] = $NRCount;
}
The if (!isset($DataArray[$id])) is to make sure it doesn't wipe out the same index row, in case you happen to re-loop on the same ID. Thus, it will only map it once, then never again in the loop.
There are some other one-line shortcuts like maybe even using array_map(), but I was showing the long version, for full flexibility just in case.
Related
I'm trying to figure out how to build the "desired" array from my "current" array.
My current array is an indexed array, but each value is actually two values separated by a |. I currently explode() each array value to produce two separate values. I'd like to convert the current array to a two-dimensional array where the 1st array is indexed and the nested array is an associative array.
I've tried several ideas, but none work. Any help to convert it programmatically is greatly appreciated.
My "Current" Array
$appInfo = array("idNum1|dir/path1","idNum2|dir/path2","idNum3|dir/path3");
My "Desired" array
$apps = array(
array("appID" => "$someVarAppID","appDir" => "$someVarAppPath"),
array("appID" => "$someVarAppID","appDir" => "$someVarAppPath"),
array("appID" => "$someVarAppID","appDir" => "$someVarAppPath"),
array("appID" => "$someVarAppID","appDir" => "$someVarAppPath")
);
Something like this will work:
$apps = array();
foreach ($appInfo as $app) {
list($id, $path) = explode('|', $app);
$apps[] = array('appId' => $id, 'appDir' => $path);
}
Output:
Array
(
[0] => Array
(
[appId] => idNum1
[appDir] => dir/path1
)
[1] => Array
(
[appId] => idNum2
[appDir] => dir/path2
)
[2] => Array
(
[appId] => idNum3
[appDir] => dir/path3
)
)
Demo on 3v4l.org
This question already has answers here:
Filter/Remove rows where column value is found more than once in a multidimensional array
(4 answers)
Closed 9 months ago.
I'm trying to remove all keys with repeated numbers, I've tried some solutions posted here like the one I'm using in my script but none of it worked for my purpose.
This is my array:
There are at least 4 card IDs repeated.
Array
(
[0] => Array
(
[id_card] => 11883834
[type] => 1
[registed] => 1547610891
)
[1] => Array
(
[id_card] => 20311077
[type] => 1
[registed] => 1547610891
)
[2] => Array
(
[id_card] => 16187903
[type] => 3
[registed] => 1547610891
)
[3] => Array
(
[id_card] => 16354099
[type] => 1
[registed] => 1547610891
)
[4] => Array
(
[id_card] => 21133393
[type] => 4
[registed] => 1547610891
)
[5] => Array
(
[id_card] => 15452852
[type] => 2
[registed] => 1547610891
)
[6] => Array
(
[id_card] => 19775869
[type] => 2
[registed] => 1547610891
)
[7] => Array
(
[id_card] => 20311077
[type] => 1
[registed] => 1547610891
)
[8] => Array
(
[id_card] => 21133393
[type] => 4
[registed] => 1547610891
)
[9] => Array
(
[id_card] => 11883834
[type] => 1
[registed] => 1547610891
)
)
1
At the moment I have something like this:
<?php
$array_data = array_map('unserialize', array_unique(array_map('serialize', $myArray)));
echo '<pre>';
print_r($array_data);
echo '</pre>';
?>
With only 10 keys is working perfectly, but when it goes through this with, for example, 50, 100 keys, no longer works.
Any help appreciated.
So the issue here is that the array_unique solutions expect the entire value to be equivalent - they don't just compare based on your ID field.
Instead, you probably want to loop through the array and keep track of which IDs you've seen, and only take those elements for which you haven't seen the ID before.
function filter_duplicate_id_cards($data) {
$seen = array(); // To keep track of the IDs we've seen
$filtered = array(); // Will hold the result
foreach($data as $item) {
if(array_key_exists($item['id_card'], $seen)) {
// We already encountered this id card before.
continue;
}
// Never-before seen id card, append it to the result and set the key in $seen
$filtered[] = $item;
$seen[$item['id_card']] = TRUE;
}
return $filtered;
}
Note that this uses the map form of a PHP array, rather than just appending seen IDs to the list form and using something like in_array to check if we've seen the key. That's important for performance reasons, especially if we're going to be working on large datasets - in_array is O(n) with the # of items in the array whereas array_key_exists is O(1).
A more generic version of this function would look like this:
function filter_duplicate_field($data, $field) {
$seen = array(); // To keep track of the keys we've seen
$filtered = array(); // Will hold the result
foreach($data as $item) {
if(array_key_exists($item[$field], $seen)) {
// We already encountered this key before.
continue;
}
// Never-before seen key, append it to the result and set the key in $seen
$filtered[] = $item;
$seen[$item[$field]] = TRUE;
}
return $filtered;
}
You could then call it like $result = filter_duplicate_field($data, 'id_card');.
This doesn't preserve the original input order, but because the data is indexed so I'll assume that that doesn't matter.
With just 3 calls in a one-liner, you assign temporary associative keys from back to front to eliminate latter duplicates (because php does not permit duplicate keys), then optionally remove the temporary keys with array_values(). No iterated function calls. No lookup arrays.
Code: (Demo)
$array = [
['id_card' => 11883834, 'type' => 1, 'registed' => 1547610891],
['id_card' => 20311077, 'type' => 1, 'registed' => 1547610891],
['id_card' => 16187903, 'type' => 3, 'registed' => 1547610891],
['id_card' => 16354099, 'type' => 1, 'registed' => 1547610891],
['id_card' => 21133393, 'type' => 4, 'registed' => 1547610891],
['id_card' => 15452852, 'type' => 2, 'registed' => 1547610891],
['id_card' => 19775869, 'type' => 2, 'registed' => 1547610891],
['id_card' => 20311077, 'type' => 1, 'registed' => 1547610891],
['id_card' => 21133393, 'type' => 4, 'registed' => 1547610891],
['id_card' => 11883834, 'type' => 1, 'registed' => 1547610891]
];
var_export(array_values(array_column(array_reverse($array), null, 'id_card')));
If you change you mind about wanting to keep the first occurrence, you can remove array_reverse(). If the first level keys are irrelevant in the output, you can remove array_values(). These changes would allow the solution to be a one function call task.
p.s. "registered"
I have the follow array:
$arrIni["ENV"]="US";
$arrIni["sap_db_server"] = "192.xxx.x.xx";
$arrIni["local_db_server"] = "localhost";
$arrIni["local_db_username"] = "root";
//Default settings
$arrIni["arrEnvSettings"]["UserTypeID"]=4;
$arrIni["arrEnvSettings"]["LocalizationID"]=1;
$arrIni["arrEnvSettings"]["LangLabels"] = array();
$arrIni["arrEnvSettings"]["pages"]["st1"]="st1.php";
$arrIni["arrEnvSettings"]["pages"]["st2"]="st2.php";
$arrIni["arrEnvSettings"]["pages"]["st3"]="st3.php";
And I want to merge with this one:
$setParam["arrEnvSettings"]["pages"]["st3"]="st3_V2.php";
This is what I am doing:
echo "<pre>";
print_r(array_merge($arrIni,$setParam));
echo "</pre>";
And this is what I am getting:
Array
(
[ENV] => US
[sap_db_server] => 192.xxx.x.xx
[local_db_server] => localhost
[local_db_username] => root
[arrEnvSettings] => Array
(
[pages] => Array
(
[st3] => st3_V2.php
)
)
)
In the php doc about merge, this is the comment " ...If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. ..."
So in this way, I suppose to get this output instead of the last one:
Array
(
[ENV] => US
[sap_db_server] => 192.xxx.x.xx
[local_db_server] => localhost
[local_db_username] => root
[arrEnvSettings] => Array
(
[UserTypeID] => 4
[LocalizationID] => 1
[LangLabels] => Array
(
)
[pages] => Array
(
[st1] => st1.php
[st2] => st2.php
[st3] => st3_V2.php
)
)
)
I do not understand why $setParam["arrEnvSettings"]["pages"]["st3"] is overriding the entire $arrIni["arrEnvSettings"].
Note:
If I use array_merge_recursive($arrIni,$setParam)) I will have the follow result but it is not what I want.
Array
(
[ENV] => US
[sap_db_server] => 192.xxx.x.xx
[local_db_server] => localhost
[local_db_username] => root
[arrEnvSettings] => Array
(
[UserTypeID] => 4
[LocalizationID] => 1
[LangLabels] => Array
(
)
[pages] => Array
(
[st1] => st1.php
[st2] => st2.php
[st3] => Array
(
[0] => st3.php
[1] => st3_V2.php
)
)
)
)
Is there a way to do this without iterate over the array? Only using merging? What am I doing wrong?
This should do the trick:
array_replace_recursive($arrIni,$setParam);
If you want to merge a given value, use this:
$arrIni["arrEnvSettings"]["pages"]["st3"] = $setParam["arrEnvSettings"]["pages"]["st3"];
But the way you're doing it is merging two arrays, not simply setting the value within an array. There's a gigantic difference between those two methods.
Otherwise, yes you will need to iteratively merge the arrays.
what you need is array_replace_recursive
print_r(array_replace_recursive($arrIni,$setParam));
didnt see the submitted answer..Felippe Duarte has given it already.....
I have this array:
Array
(
[0] => Array
(
[date] => 2016-03-08
[value] => Array
(
[key_1] => Array
(
[test_1] => 1
[test_2] => 10
[test_3] => 1000
[test_4] => 200
)
[key_2] => Array
(
[test_1] => 1
[test_2] => 15
[test_3] => 1500
[test_4] => 100
)
)
)
Now I have another array :
Array
(
[key_3] => Array
(
[test_1] =>
[test_2] =>
[test_3] =>
[test_4] => 1
)
)
I want to add this last array in the first array.
I try like this : array_push($ymlParsedData[]['value'], $a_big_gift); but not work. Can you help me please ?
You can't use $ymlParsedData[] for accessing specific element, it is a shorthand for pushing data to array.
You can use either
// NB! array_push() just adds the values, key 'key_3' is removed
array_push($ymlParsedData[0]['value'], $a_big_gift);
or
// will keep key 'key_3'
$ymlParsedData[0]['value']['key_3'] = $a_big_gift['key_3'];
or
// use array_merge() instead
$ymlParsedData[0]['value'] = array_merge($ymlParsedData[0]['value'], $a_big_gift);
A complicated answer, but this might solve your issue:
$key_name = array_keys($a_big_gift)[0];
$ymlParsedData[0]['value'][$key_name] = $a_big_gift[$key_name];
echo '<pre>'; print_r($ymlParsedData); exit;
Note: For making it dynamic and for more than one value of $a_big_gift, you need to loop it and achieve your result.
Try this
array_push($ymlParsedData[0]['value'], $a_big_gift['key_3']);
How can I merge two different multidimensional arrays but copy the keys and values from the first array to the second array?
How I'm trying to get it to work is; the first array sets the input fields, which are then cloneable (cloning using jQuery, exactly like this: http://jsfiddle.net/8M98y/). Once you save field data, the second array is the resulting output. The problem is, the second array lacks the specific keys and values from the first array that are needed to output the saved data correctly.
Is there was a way to join or merge the arrays while copying the keys and values from the first array into the second array?
The first array that I need to copy the keys/values from looks like this:
Array
(
[group-1] => Array
(
[fields] => Array
(
[text-field-1] => Array
(
[name] => Text Field 1
[value] => Value 1
[comments] => true
)
[text-field-2] => Array
(
[name] => Text Field 2
[value] => Value 2
[comments] => false
)
)
)
)
The second array looks like this:
Array
(
[group-1] => Array
(
[fields] => Array
(
[text-field-1] => New value here
[text-field-2] => New value also
)
)
[group-2] => Array
(
[fields] => Array
(
[text-field-1] => Cloned group with new value
[text-field-2] => Cloned group with new value also
)
)
)
So if these two arrays were able to be merged, would need the output of the merged array to look like this: http://pastebin.com/uzuZs73B
I've tried using just array_merge( $array2, $array1 ), but the resulting output looks like this: http://pastebin.com/DucKGMN3 where they are in fact merged, but the keys and values aren't copied over.
EDIT: Should describe a use case here.
So how this works, the initial, unsaved output is two text inputs in a group which is created by the first array. The group is cloneable, using jQuery clone (this example here: http://jsfiddle.net/8M98y/). So if you add/clone one of more groups and then save, the resulting saved data would be the second array. The strings in the second array is the actual saved input values. Those would go into [value] in the first array.
However, the output of the fields is still based on the first array, meaning it can't output the cloned groups correctly as they're not an array and don't have the same keys and values from the first array.
If anyone can provide some insight on this, it would be hugely and greatly appreciated.
Sorry if I misunderstood the question, but is merging a requirement? If you have access to both arrays you could iterate over the second array, mapping the original key values, and overwriting with the new values as you go.
Your arrays:
$arr1 = Array
(
'group-1' => Array
(
'fields' => Array
(
'text-field-1' => Array
(
'name' => 'Text Field 1',
'value' => 'Value 1',
'comments' => 'true'
),
'text-field-2' => Array
(
'name' => 'Text Field 2',
'value' => 'Value 2',
'comments' => 'false'
)
)
)
);
$arr2 = Array
(
'group-1' => Array
(
'fields' => Array
(
'text-field-1' => 'New value here',
'text-field-2' => 'New value also'
)
),
'group-2' => Array
(
'fields' => Array
(
'text-field-1' => 'Cloned group with new value',
'text-field-2' => 'Cloned group with new value also'
)
)
);
Secret sauce:
foreach($arr2 as $k=>$v){
// Get the new values for this iteration
$val1 = $arr2[$k]['fields']['text-field-1'];
$val2 = $arr2[$k]['fields']['text-field-2'];
// Duplicate the original array
$arr2[$k]['fields'] = $arr1['group-1']['fields'];
// Insert the new values
$arr2[$k]['fields']['text-field-1']['value'] = $val1;
$arr2[$k]['fields']['text-field-2']['value'] = $val2;
}
echo '<pre>';
print_r($arr2);
echo '</pre>';
exit();
Which returns:
Array
(
[group-1] => Array
(
[fields] => Array
(
[text-field-1] => Array
(
[name] => Text Field 1
[value] => New value here
[comments] => true
)
[text-field-2] => Array
(
[name] => Text Field 2
[value] => New value also
[comments] => false
)
)
)
[group-2] => Array
(
[fields] => Array
(
[text-field-1] => Array
(
[name] => Text Field 1
[value] => Cloned group with new value
[comments] => true
)
[text-field-2] => Array
(
[name] => Text Field 2
[value] => Cloned group with new value also
[comments] => false
)
)
)
)