I've got a database table that looks like this:
uid | group | category
1 | group1 | cat1
2 | group1 | cat2
3 | group2 | cat3
4 | group2 | cat4
5 | group2 | cat5
6 | group3 | cat6
7 | group3 | cat7
But I need this data in an array, that groups categories by their group.
For example, my array should look like this:
Array
(
[group1] => Array
(
[0] => Array
(
[0] => 1
[1] => cat1
)
[1] => Array
(
[0] => 2
[1] => cat2
)
)
[group2] => Array
(
[0] => Array
(
[0] => 3
[1] => cat3
)
[1] => Array
(
[0] => 4
[1] => cat4
)
[2] => Array
(
[0] => 5
[1] => cat5
)
)
[group3] => Array
(
[0] => Array
(
[0] => 6
[1] => cat6
)
[1] => Array
(
[0] => 7
[1] => cat7
)
)
)
I've written a foreach loop that does just this, but I have a problem.
My problem is that it always leaves out the very last row of the table, and I'm not sure how to fix it. In my mind, the logic dictates that it should always work.
I was thinking that after the loop I could just add the very last row to the new array, but I think that may cause issues if the last row has a different group, and I would rather the solution be built into the foreach loop.
Unfortunately, I am at a loss here. How can I fix my code to include the very last row of the database query?
I would also be interested to see what improvements I can make on my current code, but that may be a better question for codereview.
My loop:
$pass = [];
foreach($stmt as $key => $value) {
if(empty($currentGroup)) $currentGroup = $value['group'];
if(empty($temp)) $temp = [];
if($currentGroup != $value['group'] || $key+1 == count($stmt)) {
$pass[$currentGroup] = $temp;
$currentGroup = $value['group'];
$temp = [];
$temp[] = [$stmt[$key]['uid'], $stmt[$key]['category']];
} else {
$temp[] = [$stmt[$key]['uid'], $stmt[$key]['category']];
}
}
The following should do it:
<?php
//Create an array to store our grouped rows
$grouped = array();
//Loop over all rows returned by the $stmt that has been executed.
//You could probably remove the key from here, it's not needed it seems.
//The keys within the $value array will match the names of the columns in
//the database,
foreach($stmt as $key => $value){
//As we're storing by the group value from the row we first want to
//check if our grouped array contains a key for the group of the row
//being processed. If it does not, create an empty array within the
//grouped data for this group.
if(!array_key_exists($value['group'], $grouped)){
$grouped[$value['group']] = array();
}
//Knowing we will always have an array element for the rows group
//we can blindly append the values for this row to the grouped
//container using its values.
//'[] =' is just short hand append.
$grouped[$value['group']][] = array(
$value['uid'],
$value['category']
);
}
Hope that helps!
To further future proof this loop you could change the grouped value append to the following:
<?php
//Setting the whole row (minus the group) rather than just the uid
//and category explicitly allows this code to work without modification
//as the datatable changes, ie. new columns. Assuming that is the 'group'
//column remains present
unset($value['group']);
$grouped[$value['group']][] = $value;
Grouped contents data could now be accessed using the following:
<?php
//Acceess data via column name not array index, yay!
echo $grouped['group1']['uid']
I've needed this again recently, so I made a function based around #JParkinson1991's answer.
I'm putting this here for documentation, and to possibly help future readers.
function groupArray($arr, $group, $preserveSubArrays = false, $preserveGroupKey = false) {
$temp = array();
foreach($arr as $key => $value) {
$groupValue = $value[$group];
if(!$preserveGroupKey)
{
unset($arr[$key][$group]);
}
if(!array_key_exists($groupValue, $temp)) {
$temp[$groupValue] = array();
}
if(!$preserveSubArrays){
$data = count($arr[$key]) == 1? array_pop($arr[$key]) : $arr[$key];
} else {
$data = $arr[$key];
}
$temp[$groupValue][] = $data;
}
return $temp;
}
Breakdown
function groupArray($arr, $group, $preserveGroupKey = false, $preserveSubArrays = false)
This function accepts 2 to 4 parameters.
The flat array you want to group (array)
The key you want to group by (string/int)
Option to preserve the group key in the output of each sub array (Boolean)
Option to preserve sub arrays. If only 1 key exists in each sub array, the function will store just the single value for each row instead of an array (Boolean)
The first parameter is the array itself, the second parameter is the key that you want to group by, and the 3rd (optional) parameter is a boolean that tells the function if you want to preserve the group key in the sub arrays.
$temp = array();
foreach($arr as $key => $value) {
$groupValue = $value[$group];
if(!$preserveGroupKey)
{
unset($arr[$key][$group]);
}
if(!array_key_exists($groupValue, $temp)) {
$temp[$groupValue] = array();
}
$temp[$groupValue][] = $arr[$key];
}
First, we create a temporary array called $temp
Next, we loop through the array grabbing the key (Which should be a string or int), and the value (Which should be an array).
We set $groupValue to whatever the value is of the $group you chose, such as "group" in the example below.
$arr = [
0 => [
"group" => "group1",
"name" => "Bob",
],
1 => [
"group" => "group1",
"name" => "Randy",
],
2 => [
"group" => "group1",
"name" => "Susan",
],
3 => [
"group" => "group2",
"name" => "Larry",
],
4 => [
"group" => "group2",
"name" => "David",
],
5 => [
"group" => "group3",
"name" => "Perry",
],
];
Then we check if we want to $preserveGroupKey's. If this boolean is false (And it is by default), the key will be removed leaving several subarrays with just the "name" key left.
Now we check if the $groupValue exists in our $temp array, if it does not, we create it.
Then we add to the $temp[$groupValue] whatever the current row values are. From the example above, we would end up with:
Array
(
[group1] => Array
(
[0] => Bob
[1] => Randy
[2] => Susan
)
[group2] => Array
(
[0] => Larry
[1] => David
)
[group3] => Array
(
[0] => Perry
)
)
Or, with the 3rd parameter set to true you would get:
Array
(
[group1] => Array
(
[0] => Array
(
[name] => Bob
)
[1] => Array
(
[name] => Randy
)
[2] => Array
(
[name] => Susan
)
)
[group2] => Array
(
[0] => Array
(
[name] => Larry
)
[1] => Array
(
[name] => David
)
)
[group3] => Array
(
[0] => Array
(
[name] => Perry
)
)
)
Related
I have an array that need to be validated on the server.
The array look like this:
array:2 [
0 => array:5 [
"sku" => "8x0c"
"price" => "30.00"
"stock" => 5
"option_1" => 2
"option_2" => 5
]
1 => array:5 [
"sku" => "qsaz"
"price" => "30.00"
"stock" => 5
"option_1" => 2
"option_2" => 5
]
]
This array contains only 2 entries (it can contain multiple entries).
option_1, option_2 and option_3 are dynamic fields and need to be unique.
The array can have minimum one dynamic field (option_1) and maximum 3 fields (option_1, option_2 and option_3)
In this case in the first array
"option_1" => 2
"option_2" => 5
and in the second
"option_1" => 2
"option_2" => 5
are the same (i have two variations for a product that have the same color and size - and I don't want this).
How can I validate / check for duplicates for the selected options ?
If the two options keys in the items array are always going to be present, then the below function would allow you to validate the options being unique:
function validateUniqueOptions(array $items): bool
{
// Keep track the options we've seen before
$optionsSeen = [];
foreach ($items as $item) {
// Generate a unique key for this item combining its selection options
$optionKey = $item['option_1'] . '_' . $item['option_2'];
if (in_array($optionKey, $optionsSeen)) {
// This item is a duplicate of another we've seen previously, validation failed
return false;
}
$optionsSeen[] = $optionKey;
}
// No duplicates found, validation successful
return true;
}
This function below could handle as many option you'd like and if there are three options and two options in the other it is unique as well.
function check_options_duplicate($arr) {
$options_arr = ["","",""]; //Place for three options..
foreach($arr as $topkey=>$toplevel) {
foreach($toplevel as $key=>$item) {
if (substr($key,0,7) == 'option_') {
$options_arr[$topkey] .= $item . ",";
}
}
}
//If number of items in array are not the same when removing
//duplicate values with array_unique => it is a duplicate
if (count($options_arr) !== count(array_unique($options_arr))) {
return true;
}
return false;
}
Usage:
$is_duplicate = check_options_duplicate($arr);
if ($is_duplicate) {
echo 'is duplicate';
}
else {
echo 'is not duplicate';
}
Example: If having the array $arr:
Array
(
[0] => Array
(
[sku] => 8x0c
[price] => 30.00
[stock] => 5
[option_1] => 4
[option_2] => 3
)
[1] => Array
(
[sku] => qsaz
[price] => 30.00
[stock] => 5
[option_1] => 4
[option_2] => 33
)
)
it would result in the $options_arr array
Array
(
[0] => 4,3,
[1] => 4,33,
[2] =>
)
If doing an array_unique() it would be the same:
Array
(
[0] => 4,3,
[1] => 4,33,
[2] =>
)
If it both options would be the same:
Array
(
[0] => 4,3,
[1] => 4,3,
[2] =>
)
and you're doing an unique_array() it would only contain two items instead of 3.
Therefore it's a duplicate when you compare original $options_arr with unique $options_arr.
Array
(
[0] => 4,3,
[2] =>
)
I have an array which is
Array ( [0] => Array ( [picture] => 5a55ed8d8a5c8910913.jpeg
[id] => 1284
[price_range] => Rs 12000 - 9000
[name] => Brown Beauty Office Chair )
[1] => Array ( [picture] => 5a55eefeb9a8e255836.jpeg
[id] => 1285
[price_range] => Rs 8989 - 7000
[name] => Chang Series Office Chair (Grey)
)
)
Now I am fetching the value of id on clicking a remove button, the value I fetch is 1284.
I want to take out just [id]=> 1284 from the above array and then display it using a foreach loop. How I can delete just the [id]=> 1284 without disturbing the other id values and other element.
In the above array I would like to delete one particular id value say just the [id]=> 1284 and keep all other elements intact and as it is.
Any help is welcome.
Use array_search and array_column, to find by id and remove by unset method,
<?php
$array = [
["id"=>123,"desc"=>"test1"],
["id"=>456,"desc"=>"test2"],
["id"=>789,"desc"=>"test3"],
];
$id = 456;
$index = array_search($id, array_column($array, 'id'));
unset($array[$index]);
print_r($array);
?>
Live Demo
Array
(
[0] => Array
(
[id] => 123
[desc] => test1
)
[2] => Array
(
[id] => 789
[desc] => test3
)
)
Since you asked how to achieve it using foreach, I came up with this.
$array = Array (Array ( 'picture' => '5a55ed8d8a5c8910913.jpeg','id' => 1284,'price_range' => 'Rs 12000 - 9000', 'name' => 'Brown Beauty Office Chair'),
Array ( 'picture' => '5a55eefeb9a8e255836.jpeg','id' => 1285,'price_range' => 'Rs 8989 - 7000','name' => 'Chang Series Office Chair (Grey)')
);
foreach($array as $key => $val) {
$id = $array[$key]['id'];
if($id === 1284){
unset($array[$key]['id']);
}
}
print_r($array)
?>
You can also use this too:
<?php
$element_to_remove = 1284;
$i = 0;
foreach($array as $this_arr){
$index = array_search($element_to_remove, $this_arr);
//unset($this_arr[$index]); this formate does not remove element from array
//but below works fine
if(isset($array[$i][$index])){
unset($array[$i][$index]);
}
}
print_r($array);
?>
I have an array coming from my database and simply it consists of questions and answers. I am trying to merge 2 arrays and create multidimensional array if values are more than one.
Array
(
[0] => Array
(
[question_id] => 1
[option_id] => 1
)
[1] => Array
(
[question_id] => 2
[option_id] => 3
)
[2] => Array
(
[question_id] => 3
[option_id] => 5
)
[3] => Array
(
[question_id] => 3
[option_id] => 6
)
)
I've tried to separate answers and questions to 2 different arrays but couldn't figure how to merge them again.
$user_questions = array_column($answers, 'question_id');
$user_answers = array_column($answers, 'option_id');
What I need is (question 3 has 2 answers) :
Array
(
[1] => 1
[2] => 3
[3] => Array (5, 6)
)
You can group your data like this as you fetch the results from your query instead of processing it after the fact. To get the array you have now, you're currently doing something like this:
while ($row = $stmt->someFetchMethod()) {
$result[] = $row;
}
Instead, use the question id as the key in your result array, and append the option id to an array at that key.
while ($row = $stmt->someFetchMethod()) {
$result[$row['question_id']][] = $row['option_id'];
}
Below code will create a new array by looping the existing array.
// Considering your existing array to be like this
$array = array(
'0' => array('question_id' => 1,'option_id' => 1),
'1' => array('question_id' => 2, 'option_id' => 3 ),
'2' => array('question_id' => 3,'option_id' => 5),
'3' => array('question_id' => 3,'option_id' => 6)
);
//define new array
$new_array = array();
// loop the array
foreach($array as $key=>$value){
// if the option/answer is already set to to question key
if(isset($new_array[$value['question_id']])){
// if question key is an array, push new option to that array
if(is_array($new_array[$value['question_id']])){
array_push($new_array[$value['question_id']], $value['option_id']);
}else{
// convert question key to array with the old value and new option value
$new_array[$value['question_id']] = array($new_array[$value['question_id']],$value['option_id']);
}
}
else{
// assing option as value to question key
$new_array[$value['question_id']] = $value['option_id'];
}
}
print_r($new_array);
Out put:
Array
(
[1] => 1
[2] => 3
[3] => Array
(
[0] => 5
[1] => 6
)
)
I am trying to put content of one array into the same array. Here I have an array $mclass with values such as
Array
(
[0] => stdClass Object
(
[room_id] => 1,3,5
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
)
You can see I have room_id index with 1,3,5 value. Now, I want to explode the room_id and get duplicate of same array index data with change of room_id and push into the array. and finally delete the current array index such as [0]. Here I want the final result as.
Array
(
[0] => stdClass Object
(
[room_id] => 1
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
[1] => stdClass Object
(
[room_id] => 3
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
[2] => stdClass Object
(
[room_id] => 5
[day] => 1
[class_teacher] => TEA-2014-2
[final_exam_date] => 2015-09-21
)
)
Here is my code for the same:
if(count($mclass)>0)
{
foreach($mclass as $mclasskey=>$mclass_row)
{
/* Room ID Calculation */
if(isset($mclass[$mclasskey]))
{
$temp_room_id = explode(',',$mclass_row->room_id);
if(count($temp_room_id)>1)
{
foreach($temp_room_id as $trkey=>$tr)
{
if(!in_array($temp_room_id[$trkey], $morning_class_semester))
{
array_push($morning_class_semester,$temp_room_id[$trkey]);
}
}
if(count($morning_class_semester)>0)
{
foreach($morning_class_semester as $mcskey=>$mcs)
{
$index_count = count($new_test);
$test[$index_count] = $mclass[$mclasskey];
$test[$index_count]->room_id = $morning_class_semester[$mcskey];
array_push($new_test,$test[$index_count]);
}
unset($mclass[$mclasskey]);
}
}
}
}
}
The code below does what you're looking for using only arrays. So you'll have to change the array access operators to -> since you're accessing an object. I'd do so, but it would break the example, so I'll leave that up to you.
Code Explained:
Loop through array selecting each subarray (object in your case), explode on the $item('room_id') ... ($item->room_id in your case) ... and create sub arrays, via loop, from that using the data from the original using each key. Remove the original item (which has the combined room_ids) and combine the placeholder and original array.
<?php
//Establish some data to work with
$array = array(
array(
"room_id" => "1,3,5",
"day" => 1,
"class_teacher" => "TEA-2014-2",
"final_exam_date" => "2015-09-21",
));
foreach ($array as $key => $item) {
$placeholder = array();
$ids = explode(',',$item['room_id']);
if (count($ids) > 1) {
foreach ($ids as $id) {
$push = array(
'room_id' => $id,
'day' => $item['day'],
'class_teacher' => $item['class_teacher'],
'final_exam_date' => $item['final_exam_date']
);
array_push($placeholder, $push);
}
$array = array_merge($array, $placeholder);
unset($array[$key]);
}
}
var_dump($array);
?>
I have the following multidimensional array:
Array ( [0] => Array
( [id] => 1
[name] => Jonah
[points] => 27 )
[1] => Array
( [id] => 2
[name] => Mark
[points] => 34 )
)
I'm currently using a foreach loop to extract the values from the array:
foreach ($result as $key => $sub)
{
...
}
But I was wondering how do I see whether a value within the array already exists.
So for example if I wanted to add another set to the array, but the id is 1 (so the person is Jonah) and their score is 5, can I add the 5 to the already created array value in id 0 instead of creating a new array value?
So after the loop has finished the array will look like this:
Array ( [0] => Array
( [id] => 1
[name] => Jonah
[points] => 32 )
[1] => Array
( [id] => 2
[name] => Mark
[points] => 34 )
)
What about looping over your array, checking for each item if it's id is the one you're looking for ?
$found = false;
foreach ($your_array as $key => $data) {
if ($data['id'] == $the_id_youre_lloking_for) {
// The item has been found => add the new points to the existing ones
$data['points'] += $the_number_of_points;
$found = true;
break; // no need to loop anymore, as we have found the item => exit the loop
}
}
if ($found === false) {
// The id you were looking for has not been found,
// which means the corresponding item is not already present in your array
// => Add a new item to the array
}
you can first store the array with index equal to the id.
for example :
$arr =Array ( [0] => Array
( [id] => 1
[name] => Jonah
[points] => 27 )
[1] => Array
( [id] => 2
[name] => Mark
[points] => 34 )
);
$new = array();
foreach($arr as $value){
$new[$value['id']] = $value;
}
//So now you can check the array $new for if the key exists already
if(array_key_exists(1, $new)){
$new[1]['points'] = 32;
}
Even though the question is answered, I wanted to post my answer. Might come handy to future viewers. You can create new array from this array with filter then from there you can check if value exist on that array or not. You can follow below code. Sample
$arr = array(
0 =>array(
"id"=> 1,
"name"=> "Bangladesh",
"action"=> "27"
),
1 =>array(
"id"=> 2,
"name"=> "Entertainment",
"action"=> "34"
)
);
$new = array();
foreach($arr as $value){
$new[$value['id']] = $value;
}
if(array_key_exists(1, $new)){
echo $new[1]['id'];
}
else {
echo "aaa";
}
//print_r($new);