PHP - Comparing two multidimensional arrays - php

I have two arrays with data in them and I need to compare the two and create one final array.. here is my situation:
// grab a list of the folders
$folders = glob("../*",GLOB_ONLYDIR);
// create empty array's which will contain our data
$projects_data = array();
$folders_array = array();
// list the contents of the config file
$data = json_decode(file_get_contents('.my-config'), true);
// loop through our data file
foreach($data['web_app']['projects'] as $project) :
// update our projects data array
$projects_data[] = $project;
endforeach;
// loop through each folder on our localhost
foreach($folders as $folder) :
// update our folders array
$folders_array[] = array(
'folder' => basename($folder),
'last_modified' => filemtime($folder),
'dir_size' => dirsize($folder)
);
endforeach;
so I have two arrays.. like so:
$projects_data array
Array
(
[0] => Array
(
[folder] => GitHub Clones
[last_modified] => 1379974689
[dir_size] => 6148
)
[1] => Array
(
[folder] => MagentoPlayground
[last_modified] => 1380336582
[dir_size] => 82340978
)
[2] => Array
(
[folder] => Projects
[last_modified] => 1380581312
[dir_size] => 5954
)
)
$folders_array array
Array
(
[0] => Array
(
[folder] => MagentoPlayground
[last_modified] => 1380336582
[dir_size] => 82340978
)
[1] => Array
(
[folder] => Projects
[last_modified] => 1380581312
[dir_size] => 5933
)
[2] => Array
(
[folder] => old
[last_modified] => 1371064970
[dir_size] => 63385844
)
)
I need to compare these two arrays.. If there is one that exists in the top array and does not exist in the second array (Github Clones) then I need to remove it. If there is one that exist in the bottom array that does not exist in the top array (old) then I need to add it. I guess I will need a third array with the new data but I'm not sure how to structure this.
Also, if there are two entries in both arrays (MagentoPlayground) I need the new array to use the data from the bottom array. The bottom array will have the most up to date last_modified stamp and directory size.
Thanks for any help.

I'd compare using the rules you've just mentioned:
Exists in A but not in B -> remove
Exists in B but not in A -> add
...and create a third and final array. Due to the first rule, you may as well loop through array B as comparison which will solve that one.
<?php
// multidimensional array key search (one deep)
function m_array_key_exists($key, $array) {
foreach($array as $subkey => $subvalue) {
if($subkey === $key)
return true;
if(is_array($subvalue)){
if(array_key_exists($key, subvalue))
return true;
}
}
return false;
}
?>
Seems from those two rules alone that you may as well just take your second array, because if it exists in both arrays it can stay, if it doesn't exist in B you are going to remove it, but it's not there anyway, and if it exists in B but not A you add it, but it's already there...
Use m_array_key_exists as above to check one level deeper than array_key_exists() whether an array key exists in arrays like you've shown. If your rules aren't as simple as I've thought they are, it sounds to me like you want to loop through your second array, check for array keys, apply your special rules and add the result to the third array.

Related

Dynamically finding a particular array index

I have a large multi-dimensional array with multiple occurrences of #options indexes. The following is a single array example:
FORM => Array
(
[#attached] => Array
(
[library] => quiz/quiz-form-styling
)
[text_0] => Array
(
[#type] => markup
[#markup] =>
Wherelese did Walter White work besides being a teacher?
)
[radio_1] => Array
(
[#type] => radios
[#options] => Array
(
[0] => An elder Care home
[1] => [A car wash]
[2] => A beauty saloon
[3] => For Skylers old boss
)
[#correct] => testing_correct_for radio
)
[text_2] => Array
(
[#type] => markup
[#markup] =>
)
)
In the example above, the parent array of #options is radio_1. But that is not always the case as the arrays are dynamically generated. There is no way to know in advance what the parent index would be but there is always an #options index.
What I'm trying to figure out is how to find and retrieve the data in all occurrences of #options. How can I do that?
I'd suggest iterating the set of form elements and checking if an inner #options key exists. If so, you can add the options to your array of all options.
$all_options = [];
foreach ($form_elements as $name => $settings) {
if (isset($settings['#options'])) {
$all_options[$name] = $settings['#options'];
}
}
I used the element name as key in the example code, because I thought it seemed like it would be convenient to know where the options came from, but you wouldn't have to do it that way. If you just wanted them all in one big list, you could merge them onto $all_options instead of appending them.
$all_options = array_merge($all_options, $settings['#options']);
This is assuming each of the values under FORM is an array representing one form element. If there is any nesting such that #options could appear at a deeper level, a recursive search could handle that, but if not, I think it's best to keep it simple.
You can try something like recursive function
Here is simple example for above case.
$alloptions = array();
function seach($searcharray){
foreach($searcharray as $key=>$value){
if($key == '#options'){
$alloptions[] = $searcharray[$key];
}else if(is_array($value)){
seach($value);
}
}
}

codeigniter directory map helper - folder permissions

I am using dircetory_helper() to list all directories and files. However, when I change the permissions of a folder to 0700 (so it cannot be seen or accessed), it is still appearing in the array. Like so;
Array
(
[2001-07-01/] => Array
(
[0] => 1_july_2001.pdf
)
[0] => introduction.html
[2009-05-01/] =>
[2012-07-01/] => Array
(
[0] => 1_july_2012.pdf
[1] => 1_july_2012.xls
)
[2013-01-01/] => Array
(
[0] => 1_january_2013.pdf
[1] => key_points.html
[2] => 1_january_2013.xls
)
)
Look at the 2009-05-01/ key. I do not want this to appear in the array. At the moment it is appearing as an array key but what is the item? Is it NULL?
Is there a fix for this? I am using codeigniter version 2.1.3
At the moment it is appearing as an array key but what is the item? Is it NULL?
It is an empty array. Is is boolean (false). So long as it's not showing the contents, what is the problem? When you are displaying the array, there isn't anything in the array so it (nor it's key) should be displayed.
if( count($array_item) == 0 )
{
// dont show $array_item
}
else
{
// $array_item with stuff in it; display
}
I don't think there is a way to prevent the key from getting in there without changing the permissions on the parent directory which will then obviously prevent the rest of the dir's from being read too. By changing the folder to 0700, it is acting as expected by not rendering the contents of the directory.
However, you can modify the result of directory_map() before sending it back:
$this->load->helper('directory');
$map = directory_map('testdir');
$my_map = array();
foreach($map as $k => $v )
{
// check that it's not an empty array and that it's not a file
// in the root directory
if($v and gettype($v) == 'array')
{
$my_map[$k] = $v;
}
}
print_r($my_map);

php remove duplicates based on first value of multidimensional array

Given
[0] => Array
(
[0] => ask.com
[1] => 2320476
)
[1] => Array
(
[0] => amazon.com
[1] => 1834593
)
[2] => Array
(
[0] => ask.com
[1] => 1127456
)
I need to remove duplicate values solely based on first value, regardless of what any other subsequent values may be. Notice [0][1] differs from [2][1] yet I consider this as a duplicate because there are two matching first values. The other data is irrelevant and shouldn't be considered in comparison.
Try this, assuming that $mainArray is the array you have.
$outputArray = array(); // The results will be loaded into this array.
$keysArray = array(); // The list of keys will be added here.
foreach ($mainArray as $innerArray) { // Iterate through your array.
if (!in_array($innerArray[0], $keysArray)) { // Check to see if this is a key that's already been used before.
$keysArray[] = $innerArray[0]; // If the key hasn't been used before, add it into the list of keys.
$outputArray[] = $innerArray; // Add the inner array into the output.
}
}
print_r($outputArray);

Array in array in array

I'm a bit struggling with the associative arrays in associative arrays. Point is that I always have to drill deeper in an array and I just don't get this right.
$array['sections']['items'][] = array (
'ident' => $item->attributes()->ident,
'type' => $questionType,
'title' => $item->attributes()->title,
'objective' => (string) $item->objectives->material->mattext,
'question' => (string) $item->presentation->material->mattext,
'possibilities' => array (
// is this even neccesary to tell an empty array will come here??
//(string) $item->presentation->response_lid->render_choice->flow_label->response_label->attributes()->ident => (string) $item->presentation->response_lid->render_choice->flow_label->response_label->material->mattext
)
);
foreach ($item->presentation->response_lid->render_choice->children() as $flow_label) {
$array['sections']['items']['possibilities'][] = array (
(string) $flow_label->response_label->attributes()->ident => (string) $flow_label->response_label->material->mattext
);
}
So 'possibilities' => array() contains an array and if I put a value in it like the comment illustrates I get what I need. But an array contains multiple values so I am trying to put multiple values on the position $array['sections']['items']['possibilities'][]
But this outputs that the values are stores on a different level.
...
[items] => Array
(
[0] => Array
(
[ident] => SimpleXMLElement Object
(
[0] => QTIEDIT:SCQ:1000015312
)
[type] => SCQ
...
[possibilities] => Array
(
)
)
[possibilities] => Array
(
[0] => Array
(
[1000015317] => 500 bytes
)
[1] => Array
...
What am trying to accomplish is with my foreach code above is the first [possibilities] => Array is containing the information of the second. And of course that the second will disappear.
Your $array['sections']['items'] is an array of items, so you need to specify which item to add the possibilities to:
$array['sections']['items'][$i]['possibilities'][]
Where $i is a counter in your loop.
Right now you are appending the Arrays to [items]. But you want to append them to a child element of [items]:
You do:
$array['sections']['items']['possibilities'][] = ...
But it should be something like:
$array['sections']['items'][0]['possibilities'][] = ...
$array['sections']['items'] is an array of items, and as per the way you populate the possibilities key, each item will have it's own possibilities. So, to access the possibilities of the item that is being looped over, you need to specify which one from $array['sections']['items'] by passing the index as explained in the first answer.
OR
To make things simpler, you can try
Save the item array (RHS of the first =) to a separate variable instead of defining and appending to the main array at the same time.
Set the possibilities of that variable.
Append that variable to the main $array['sections']['items']
I have:
array[{IsChecked: true, SEC: 0, STP: 0},
{IsChecked: ture ,SEC: 0, STP: 1},
{IsChecked: false, SEC: 1 ,STP: 0}]
How to get each SEC where IsCheked value is true?

Get key values from multidimensional array

I have a page that searches a database and generates the following array. I'd like to be able to loop through the array and pick out the value next assigned to the key "contact_id" and do something with it, but I have no idea how to get down to that level of the array.
The array is dynamically generated, so depending on what I search for the index numbers under "values" will change accordingly.
I'm thinking I have to do a foreach starting under values, but I don't know how to start a foreach at a sublevel of an array.
Array (
[is_error] => 0
[version] => 3
[count] => 2
[values] => Array (
[556053] => Array (
[contact_id] => 556053
[contact_type] => Individual
[first_name] => Brian
[last_name] => YYY
[contact_is_deleted] => 0
)
[596945] => Array (
[contact_id] => 596945
[contact_type] => Individual
[first_name] => Brian
[last_name] => XXX
[contact_is_deleted] => 0
)
)
)
I've looked at the following post, but it seems to only address the situation where the array indices are sequential.
Multidimensional array - how to get specific values from sub-array
Any ideas?
Brian
You are correct in your assumption. You could do something like this:
foreach($array['values'] as $key => $values) {
print $values['contact_id'];
}
That should demonstrate starting at a sub level. I would also add in your checks to see if its empty and if its an array... etc.
Another hint regarding syntax - if the array in your original example is called $a, then the values you want are here:
$a['values'][556053]['contact_id']
and here:
$a['values'][596945]['contact_id']
So if there's no additional structure in your array, then this loop is probably what you want:
foreach ($a['values'] as $toplevel_id => $record_data) {
print "for toplevel_id=[$toplevel_id], contact_id=[" . $record_data['contact_id'] . "]\n";
}
foreach($array['values'] as $sub_arr){
echo $sub_arr['contact_id'];
}

Categories