Two Arrays, One Output (How to ForEach?) - php

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.

Related

How to remove an item from a nested array in PHP?

I have a complicated nested array which I want to remove all items and their children with specific store_id:
It's really difficult and I don't know how to figure it out.
Array
(
[0] => Array
(
[cart_id] => 89
[product_id] => 46
[store_id] => 2
[option] => Array
(
[0] => Array
(
[product_option_id] => 92
[value] => Aqua
)
[1] => Array
(
[product_option_id] => 91
[value] => 85C
)
)
)
[1] => Array
(
[cart_id] => 90
[product_id] => 46
[store_id] => 2
)
Many thanks for any kind help.
If you want to remove the entire array element if it has a specific store_id, you just need to loop over the array, check the store_id and remove the element if you don't want it anymore.
E.g.:
<?php
foreach($data as $key=>$row){
if($row['store_id'] == 2){
unset($data[$key]);
}
}
?>
You can change that '2' to be anything you want to specifically remove a store. Or you could change the if to match an array of ids if you want to match several stores.
Here is the example for unsetting the cart_id in multi dimensional array.
<?php
foreach($data as $key=>$row){
unset($data[$key]['cart_id']);
}
?>

PHP match values between 2 arrays not same key

I have made researches and havent fount any solutions for this yet. So final thought is come to Stackoverflow and ask the question.
I have 2 array like below:
BigArray
Array
(
[0] => Array
(
[id] => 1
[category_name] => Accountancy
[category_name_vi] => Kế toán
[category_id] => 1
)
[1] => Array
(
[id] => 2
[category_name] => Armed forces
[category_name_vi] => Quân đội
[category_id] => 2
)
[2] => Array
(
[id] => 3
[category_name] => Admin & Secretarial
[category_name_vi] => Thư ký & Hành chính
[category_id] => 3
)
[3] => Array
(
[id] => 4
[category_name] => Banking & Finance
[category_name_vi] => Tài chính & Ngân hàng
[category_id] => 4
)
)
and SmallArray:
Array
(
[0] => Array
(
[id] => 7
[category_id] => 2
[jobseeker_id] => 1
)
[1] => Array
(
[id] => 8
[category_id] => 3
[jobseeker_id] => 1
)
)
Ok, now I wanted to match each category_id from SmallArray link with respectively category_name from BigArrayand the output I only need matched values between SmallArray and BigArraywhere category_id of SmallArray is key and category_name of BigArray is value like below:
Matched array:
Array
(
[0] => Array
(
[2] => Armed forces
)
[1] => Array
(
[3] => Admin & Secretarial
)
)
So far, I have tried array_intersect, 2 foreach loops but no luck. Any advise would be very appreciated :(
Thanks
This should do that:
foreach ($smallArray as $smallKey => $smallElement) {
foreach ($bigArray as $bigKey => $bigElement) {
if ($bigElement['id'] == $smallElement['category_id']) {
$smallArray[$smallKey] = array(
$bigElement['id'] => $bigElement['category_name'],
);
break; // for performance and no extra looping
}
}
}
After these loops, you have what you want in $smallArray.

How to classify array items?

I have a query which fetches all comments for question and answers in one page (each page is containing at least one post (question), and maybe plus one or more posts (answers)). Now I need to separate comments according to its own question or answers.
The result of my query (fetching all comments) is something like this:
while ($results = $sth->fetch(PDO::FETCH_ASSOC)) {
echo '<pre>';
print_r($results);
}
/* Output:
Array
(
[id] => 1
[post_id] => 1
[content] => Have you any tried so far?
)
Array
(
[id] => 2
[post_id] => 3
[content] => Great answer, upvote
)
Array
(
[id] => 3
[post_id] => 3
[content] => That semicolon is redundant in line 5. Pplease edit it
)
Array
(
[id] => 4
[post_id] => 2
[content] => Won't work ...!
)
Array
(
[id] => 5
[post_id] => 3
[content] => #alex You are right thanks, Edited.
)
So, as you see in the output, all comments are mixed.. Now I need to classify them. Something like this:
/* NewOutput:
[1] => Array
post_id ^ (
[0] => Array
(
[id] => 1
[content] => Have you any tried so far?
)
)
[2] => Array
post_id ^ (
[0] => Array
(
[id] => 4
[content] => Won't work ...!
)
)
[3] => Array
post_id ^ (
[0] => Array
(
[id] => 2
[content] => Great answer, upvote
)
[1] => Array
(
[id] => 3
[content] => That semicolon is redundant in line 5. Pplease edit it
)
[2] => Array
(
[id] => 5
[content] => #alex You are right thanks, Edited.
)
)
Well, Now I want to know, how can I create a nested array according to the value of specific key in the array? exactly like above.
Try this...
$output = array();
foreach($results as $r){
$key = "post_".$r["post_id"];
if(!array_key_exists($key, $output)){
$output[$key] = array();
}
array_push($output[$key], array("id"=>$k["id"], "content"=>$k["content"]));
}
print_r($output);

Recursive loop for category

I'm trying to implement a category system on my website. The problem is that a category can have child.
So far, my table category looks like that :
id, name, parent_id
So far, I made a loop, but it only works for 2 levels. Here is my code :
for($i=0;$i<count($data);$i++){
$tree[$data[$i]->name] = array();
for($j=0;$j<count($data);$j++){
if($data[$j]->parent_id == $data[$i]->id){
$tree[$data[$i]->name][] = $data[$j]->name;
}
}
}
It return me an array as it :
Array
(
[0] => Array
(
[1] => Cat1
[children] => Array
(
[12] => sub cat 1
[13] => sub cat 2
[14] => sub cat 3
)
)
[1] => Array
(
[2] => Cat2
)
[2] => Array
(
[3] => Cat3
)
)
How can I make it efficient and recursive to have something more like :
Array
(
[0] => Array
(
[1] => Cat1
[children] => Array
(
[12] => sub cat 1
[13] => sub cat 2
[14] => sub cat 3
[children] => Array
(
[1] => sub sub cat 1
)
)
)
[1] => Array
(
[2] => Cat2
)
[2] => Array
(
[3] => Cat3
)
)
Thanks for your help
EDIT
I'm working on Zend, and it return me the data as it :
Zend_Db_Table_Rowset Object
(
[_data:protected] => Array
(
[0] => Array
(
[id] => 1
[name] => Cinema
[type] => category
[slug] => cinema
[parent_id] => -1
)
[1] => Array
(
[id] => 2
[name] => Horror
[type] => category
[slug] => horror
[parent_id] => 1
)
If you want to apply this type of structure best to use child in other table with parent id as a foreign key.
so with that u can have recursive category posting.
so the table structure will be like this
ch_id, parent_id, child
You should check out Nested Sets, a methodology to store and retrieve date trees in/out of relational databases (what in fact your categories are). For this, you have to adapt your database scheme a little bit (as described in the link or in the several tutorials about nested sets). For PHP, there are several libraries providing Nested Set capabilities, for instance this list.
This should help you out.
It Iterates over every member of the array and checks it's position in the tree structure per level and dependency.
function get_children($data, $parent_id = false) {
$result = array();
foreach ($data as $i => $content) {
if ($parent_id != false && $content['id'] != $parent_id) # other levels
continue;
if ($parent_id === false && !empty($content['parent_id'])) # top level
continue;
$leaf = array(
'id' => $content['id'],
'parent_id' => $content['parent_id'],
'name' => $conten['name']
);
$leaf['children'] = get_children($data, $leaf['id']);
$result[$leaf['id']] = $leaf;
}
return $result;
}
$result = get_children($data);
print_r($result);
Edit: bug fixes

PHP Array Data Manipulation

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;
}
}

Categories