PHP Array Data Manipulation - php

I have a list of items stored in a DB and after requesting them, they are in an array ($data). Now there are about 200 items in the array and each of them itself is a key value array. Each element in the data array has a key called [Acr] and a name assigned to it.
Now the problem is that in this array
Array
(
[0] => Array
(
[ID] => 2
[Name] => Name Here
[Acr] => ARR
[Valid] => 1
[Orig] => 1
)
[1] => Array
(
[ID] => 2
[Name] => Name Here
[Acr] => ABC
[Valid] => 1
[Orig] => 1
)
[2] => Array
(
[ID] => 2
[Name] => Name Here
[Acr] => XYZ
[Valid] => 1
[Orig] => 1
)
...
There are items that have the same Acr but are sub elements of the first item with that Acr. So for example there are 10 more items in $data that have the Acr as ARR and I want to add those sub elements into the original (aka the first) array item with that Acr value under the key called sub. So after iterating it makes this.
Array
(
[0] => Array
(
[ID] => 2
[Name] => Name Here
[Acr] => ABC
[Valid] => 1
[Orig] => 1
)
.....
[14] => Array
(
[ID] => 2
[Name] => Name Here
[Acr] => ARR
[Valid] => 1
[Orig] => 1
[Sub] =>
[0] => Array
(
[ID] => 23
[Name] => Sub Name Here
[Acr] => ARR
[Valid] => 1
[Orig] => 0
)
[1] => Array
(
[ID] => 24
[Name] => Sub Name Here
[Acr] => ARR
[Valid] => 0
[Orig] => 1
)
)
...
Now im not sure how to do this. Also, its all sorted so when you see the first ARR all the sub ARR are right under them and there are only about 5 original categories that have sub elements so if theres a way that can do this by knowing which ones to append, that would be great.
I'm not sure if I explained the problem correctly, so if you have any questions please just ask me and I will reply within minutes.
Thanks

For the case, that alpha-numeric keys are accepted in manipulated array:
$new = array();
foreach ($array as $entry) {
if (!array_key_exists($entry['Acr'], $new)) {
$entry['Sub'] = array();
$new[$entry['Acr']] = $entry;
} else $new[$entry['Acr']]['Sub'][] = $entry;
}

An attempt at a small function that can do this, test it and let me know if it works
$newRecord = array();
foreach($records as $record){
# if the Acr already exists in a primary record,
# insert this record as a Sub-record.
if(array_key_exists($record['Acr'], $newRecord)){
$newRecord[$record['Acr']]['Sub'][] = $record;
# else insert it as a primary record
} else {
$newRecord[$record['Acr']] = $record;
}
}

Related

Insert auto generated multidimensional array to database

I need to create a db function for multidimensional array. How deep the array currently dont know, bcoz they will come from xml file.
I have a sample array
Array
(
[employee] => Array
(
[0] => Array
(
[name] => Array
(
[lastname] => Kelly
[firstname] => Grace
)
[hiredate] => October 15, 2005
[projects] => Array
(
[project] => Array
(
[0] => Array
(
[product] => Printer
[id] => 111
[price] => $111.00
)
[1] => Array
(
[product] => Laptop
[id] => 222
[price] => $989.00
)
)
)
)
[1] => Array
(
[name] => Array
(
[lastname] => Grant
[firstname] => Cary
)
[hiredate] => October 20, 2005
[projects] => Array
(
[project] => Array
(
[0] => Array
(
[product] => Desktop
[id] => 333
[price] => $2995.00
)
[1] => Array
(
[product] => Scanner
[id] => 444
[price] => $200.00
)
)
)
)
[2] => Array
(
[name] => Array
(
[lastname] => Gable
[firstname] => Clark
)
[hiredate] => October 25, 2005
[projects] => Array
(
[project] => Array
(
[0] => Array
(
[product] => Keyboard
[id] => 555
[price] => $129.00
)
[1] => Array
(
[product] => Mouse
[id] => 666
[price] => $25.00
)
)
)
)
)
)
I need to enter these type of array to db and then retrieve them in a good non programmer readable format
I created 2 table... 1st for array key with array level field and another for key=value
I tried this
function array_Dump($array, $d=1){
if (is_array($array)){
foreach($array as $key=>$val){
for ($i=0;$i<$d;$i++){
$level=$i;
}
if (is_array($val)){
if (is_int($key)){
array_Dump($val, $d+1);
}else{
$query = "insert into xml_array (level, input) VALUES ('$level','$key')";
insert_sql($query);
array_Dump($val, $d+1);
}
} else {
$query = "insert into xml_data (array_id,level_id, array_key,array_value) VALUES ('$insert_id','$level','$key','$val')";
insert_sql($query);
}
}
}
}
Create a table like this:
attributes(id, parent_id, properties)
where id will be the primary key, parent_id will be the id of the parent record and properties will be a small json field with the atomic properties. This way you support any depth the XML may throw towards your direction.
As about non-programmer representation. For instance you could use a table (you can solve that with divs as well) which will contain a row for each element in the top level array. Such a row would contain separate columns for each property. When a property is an array, then the given cell will be a table of its own, which will be handled similarly as the first table. It is advisable to make the inner tables collapsible, so if one wants to see the main levels only, the user will not have to scroll for a long while.

Search value in same array and replace it

I have this array
Array
(
[0] => Array
(
[id] => 15
[parent] => #
[text] => Shb2-1
)
[1] => Array
(
[id] => 17
[parent] => 16
[text] => Shb2-3
)
[2] => Array
(
[id] => 18
[parent] => 17
[text] => Shb2-4
)
)
I would like to search if [parent] value exist in the same array as [id]
If it do not exist exists, then the [parent] value will be replaced to 0.
Example:
check if the value 16 exists in the whole array as [id] (in my example available [id] are 15, 17 and 18).
if it do not exist, 16 will be replaced by 0.
Then check for the next array key, and so until I get un output with final replaced values.
Thank you for your help.
If you wanted to change parent to zero if it is not equal to any id, then I think this simple code will do it:
foreach ($array as $key => $val) {
// Search if 'id' exists in the array
$a_key = array_search($val['parent'], array_column($array, 'id'));
// Check if 'id' is in the array, if not then replace 'parent' with 0
if ($a_key == false) $array[$key]['parent'] = '0';
}

Friends highscore: merging two arrays

I'm developing a game on Facebook and want to show the users a friends highscore.
What's the most efficient way to do this?
I have two arrays:
The first one, $all, coming from my database, holds the fbid's and the score's of ALL users who played the game:
Array
(
[0] => Array
(
[uid] => 12345
[score] => 0
[endgame] => 1404316845
)
[1] => Array
(
[uid] => 112873
[score] => 0
[endgame] => 1404334512
)
...
)
The second one, $friends, coming from Facebook, holds ALL the user's friends:
Array
(
[0] => Array
(
[uid] => 12345
[name] => Some Name
[pic_square] => https://...
)
[1] => Array
(
[uid] => 43324324
[name] => Another Name
[pic_square] => https://...
)
[2] => Array
(
[uid] => 4893424242
[name] => Yet Another
[pic_square] => https://...
)
...
)
I think the prefered method here is to generate an new array, which contains only friends who played the game and have a score, like this:
Array
(
[0] => Array
(
[uid] => 12345
[name] => Some Name
[pic_square] => https://...
[score] => 0
[endgame] => 1404316845
)
...
)
I've tried various things using in_array, but can't get it right... Anyone who can help me?
Create a new array for the scores that is indexed by uid.
$indexedScores = [];
foreach($all as $score) {
$indexedScores[$score['uid']] = $score['score'];
}
Then loop through the friends array and set the score by looking up $indexedScores
foreach($friends as $key => &$friend) {
if(isset($indexedScores[$friend['uid']])) {
$friend['score'] = $indexedScores[$friend['uid']];
}
else {
unset($friends[$key]); //doesn't have a score, so remove
}
}
usort($friends, function($a, $b) {
return $a['score'] > $b['score'];
});

Arbitrary element in array (the value) to a key that is an array

So, I have an array that looks like this:
$grades =
Array(
[0] => Array ( [Grade] => Array ( [id] => 0 [name] => Kindegarten ) )
[1] => Array ( [Grade] => Array ( [id] => 1 [name] => First ) )
[2] => Array ( [Grade] => Array ( [id] => 2 [name] => Second ) )
[3] => Array ( [Grade] => Array ( [id] => 3 [name] => Third ) )
[4] => Array ( [Grade] => Array ( [id] => 4 [name] => Fourth ) )
[5] => Array ( [Grade] => Array ( [id] => 5 [name] => Fifth ) )
)//End array
I am wondering is there a way to arbitrarily way to pick a key (the first 0-5)? CakePHP returns the items in my table like this and I don't understand how I can conform the to the printing of Form helper with the options.
echo $this->Form->input('grade_selection',
array('type' => 'radio', 'options' => array($grades[?]['Grade']['id'] => $grades[?]['Grade']['name'])));
The ? being how to get it to change in the option so I can get each of the items in the array?
class GradesController extends AppController {
public function index(){
//Gets all the rows in the grade table and stores it into a variable called grade.
//$grades = $this->Grade->find('all');
$grades = $this->Grade->getGrades();
//Returns the $grades variable when it is requested.
if($this->request->is('requested')){
return $grades;
}
//Sends the $grades variable to the view file. The string 'grades' is the name of the variable that the Grades View file will have the same setup as the $grades.
$this->set('grades', $grades);
}
}
I am wondering is there a way to arbitrarily way to pick a key (the first 0-5)?
Yes, php, not CakePHP
$keys = array_keys($grades);
$foo = $keys[rand(0, count($keys) - 1)]
Now, I don't think that's what you need. I see you are using a radio button, what do you want to display in the radio button(s)?
EDIT
Assuming this data come from a Model named "Grade", you would do this in your crontroller
$grades = $this->Grade->find('list');
$this->set(compact('grades'));
Then, in your view:
echo $this->Form->input('grade_selection', array('options' => $grades));

Two Arrays, One Output (How to ForEach?)

Is there a way to foreach() through one array based on a matching value with a different key in another array? In this example, I have a category array ($cat_data) with cat_id as a key and an image array ($img_data) with category_id as a key.
Array (
[0] => Array (
[cat_id] => 1
[cat_name] => Category 1
)
[1] => Array (
[cat_id] => 2
[cat_name] => Category 2
)
)
Array (
[0] => Array (
[img_id] => 2
[img_name] => demo1.jpg
[img_label] => Demo 1
[category_id] => 2
[img_order] => 1
)
[1] => Array (
[img_id] => 3
[img_name] => demo2.jpg
[img_label] => Demo 2
[category_id] => 2
[img_order] => 2
)
[2] => Array (
[img_id] => 4
[img_name] => demo3.jpg
[img_label] => Demo 3
[category_id] => 1
[img_order] => 1
)
)
What I want is to output my display so it looks like the following:
Category 1
demo3.jpg
Category 2
demo1.jpg
demo2.jpg
Since I'm really not great at fully grasping arrays, I thought I'd try Stack, and I haven't been able to find an answer to my question, partially because I'm not sure what to ask for precisely. Any help??
The naïve way:
foreach ($cat_data as $cat) {
echo $cat['cat_name'];
foreach ($img_data as $img) {
if ($img['category_id'] != $cat['cat_id']) {
continue;
}
echo $img['img_name'];
}
}
This is rather inefficient, since it loops through the $imgs array several times, but easy and works.
More efficient:
$images = array();
foreach ($img_data as $img) {
$images[$img['category_id']][] = $img;
}
foreach ($cat_data as $cat) {
echo $cat['cat_name'];
if (isset($images[$cat['cat_id']])) {
foreach ($images[$cat['cat_id']] as $img) {
echo $img['img_name'];
}
}
}
This first groups all images by category into a new array, which you can then loop over directly once.
I would urge you to redesign your array when you fill them with data to instead look something like this.
Array (
[0] => Array (
[cat_id] => 1
[cat_name] => Category 1
[images] = Array(
[0] => Array (
[img_id] => 4
[img_name] => demo3.jpg
[img_label] => Demo 3
[category_id] => 1
[img_order] => 1
)
)
)
[1] => Array (
[cat_id] => 2
[cat_name] => Category 2
[images] = Array(
[0] => Array (
[img_id] => 4
[img_name] => demo3.jpg
[img_label] => Demo 3
[category_id] => 1
[img_order] => 1
)
[1] => Array (
[img_id] => 2
[img_name] => demo1.jpg
[img_label] => Demo 1
[category_id] => 2
[img_order] => 1
)
)
)
)
Then you would have all the relational data connected and would just have to loop through your array of categories and print the images associated with each one in turn. The numbered indexes could even be changed to associative names if the id of the catagory weren't important for example. Then the array could be indexed with the name of the category and just contain the images of that category.
If the images are to be used in other places where you initial layout of those fits better you could still use this layout for your main data graph. Just replace the actual data of the images in the images array under each category with a reference to the actual image object.

Categories