Group objects in php with similar course_id - php

I have a variable $items that has following data inside it.
Array
(
[0] => stdClass Object
(
[course_id] => 8
[doc_id] => 85
[doc_title] => PDF Notes
[doc_price] => 243
)
[1] => stdClass Object
(
[course_id] => 6
[doc_id] => 73
[doc_title] => PDF Notes
[doc_price] => 12
)
[2] => stdClass Object
(
[course_id] => 6
[doc_id] => 75
[doc_title] => Audio Topics
[doc_price] => 21
)
[3] => stdClass Object
(
[course_id] => 6
[doc_id] => 77
[doc_title] => Video Past Papers
[doc_price] => 32
)
)
I want to categorize the data. The course_id should become the key and the courses that have similar course_id should be categorized and become the value of that key. Like in the about array, [1], [2] and [3] have same course_id so the for key => 6, an array should be made with sub array that have docs 73, 75 and 77.
array => (
'6' => 'array of docs with course_id 6',
'8' => 'array of docs with course_id 8',
)
VAR_EXPORT
array (
0 =>
stdClass::__set_state(array(
'course_id' => '8',
'doc_id' => '85',
'doc_title' => 'PDF Notes',
'doc_price' => '243',
)),
1 =>
stdClass::__set_state(array(
'course_id' => '6',
'doc_id' => '73',
'doc_title' => 'PDF Notes',
'doc_price' => '12',
)),
2 =>
stdClass::__set_state(array(
'course_id' => '6',
'doc_id' => '75',
'doc_title' => 'Audio Topics',
'doc_price' => '21',
)),
3 =>
stdClass::__set_state(array(
'course_id' => '6',
'doc_id' => '77',
'doc_title' => 'Video Past Papers',
'doc_price' => '32',
)),
)

Try this:
use get_object_vars to convert obj to array.
$newarray = array();
foreach ($items as $item)
{
$newarray[$item->course_id][] = get_object_vars($item);
}

Related

sort array by multiple keys with optional key

The following array contains a sample of data from a larger data set -
$data =
[
[
'readingSequence' => '35',
'bookID' => '19',
'chapter' => '130'
],
[
'readingSequence' => '19',
'bookID' => '19',
'chapter' => '27'
],
[
'readingSequence' => '59',
'bookID' => '19',
'chapter' => '133'
],
[
'readingSequence' => '35',
'bookID' => '19',
'chapter' => '129'
],
[
'readingSequence' => '98',
'bookID' => '75',
'chapter' => '6',
'verses' => '11-20,',
'versesFirst' => '11'
],
[
'readingSequence' => '99',
'bookID' => '75',
'chapter' => '6',
'verses' => '1-10',
'versesFirst' => '1'
]
];
The use case requires that the elements of $data be sorted by bookID, then chapter, then versesFirst if that key exists.
The following code successfully sorts the array by bookID and chapter but I haven't figured out a way to also sort by versesFirst because it is present in some elements but not in others -
array_multisort(array_column($data, 'bookID'), SORT_ASC, array_column($data, 'chapter'), SORT_ASC, $data);
Here is the result:
Array
(
[0] => Array
(
[readingSequence] => 19
[bookID] => 19
[chapter] => 27
)
[1] => Array
(
[readingSequence] => 35
[bookID] => 19
[chapter] => 129
)
[2] => Array
(
[readingSequence] => 35
[bookID] => 19
[chapter] => 130
)
[3] => Array
(
[readingSequence] => 59
[bookID] => 19
[chapter] => 133
)
[4] => Array
(
[readingSequence] => 98
[bookID] => 75
[chapter] => 6
[verses] => 11-20,
[versesFirst] => 11
)
[5] => Array
(
[readingSequence] => 99
[bookID] => 75
[chapter] => 6
[verses] => 1-10
[versesFirst] => 1
)
)
Elements 0 to 3 are sorted correctly but elements 4 and 5 are not because versesFirst is not included. When an attempt was made to include it this warning was displayed and the results looked the same as shown above.
Warning: array_multisort(): Array sizes are inconsistent in C:\development\scratchpad.php on line 122
I could add [versesFirst] => '' to the elements that don't have the versesFirst key so that it could be included in the multisort but I'd rather not resort to that. Is there a way to include optional keys in the multisort? Or is there a different approach entirely to achieve the desired result set?
You can use usort to accomplish this with isset checks for versesFirst key.
Snippet:
<?php
usort($data, function($a,$b){
$book_id_1 = intval($a['bookID']);
$book_id_2 = intval($b['bookID']);
if($book_id_1 != $book_id_2) return $book_id_1 <=> $book_id_2;
$chapter_1 = intval($a['chapter']);
$chapter_2 = intval($b['chapter']);
if($chapter_1 != $chapter_2) return $chapter_1 <=> $chapter_2;
if(!isset($b['versesFirst'])){
return -1;
}
if(!isset($a['versesFirst'])){
return 1;
}
return intval($a['versesFirst']) <=> intval($b['versesFirst']);
});
print_r($data);

merge two arrays by specific fields

I have an array that looks like
$firstArray
[0] => Array(
[ID] => 1
[Fruit] => Apple
[State] => Ohio
)
[1] => Array(
[ID] => 2
[Fruit] => Orange
[State] => Hawaii
)
[2] => Array(
[ID] => 3
[Fruit] => Orange
[State] => Vermont
)
And another array which looks like
$secondArray
[0] => Array(
[ID] => 1
[description] => This is sample description
[Price] => 20
)
[1] => Array(
[ID] => 1
[Fruit] => This is sample description 2
[Price] => 15
)
[2] => Array(
[ID] => 2
[Fruit] => This is the second description
[Price] => 100
)
[3] => Array(
[ID] => 2
[Fruit] => This is the second description 2
[Price] => 50
)
[4] => Array(
[ID] => 3
[Fruit] => This is the third description
[Price] => 99
)
I have used
$newArray = array_merge_recursive($firstArray, $secondArray);
This has only appended entries from the second array to the end of the first array ideally i would want the new array to look like this
[0] => Array(
[ID] => 1
[Fruit] => Apple
[State] => Ohio
[description]
Array(
[0] => This is sample description
[1] => This is sample description 2
)
[price]
Array(
[0] => 20
[1] => 15
)
[1] => Array(
[ID] => 1
[Fruit] => Apple
[State] => Ohio
[description]
Array(
[0] => This is the second description
[1] => This is the second description 2
)
[price]
Array(
[0] => 100
[1] => 50
)
Essentially the new array should be combined on the ID and create nested arrays from the second array.
See if this makes sense. https://iconoun.com/demo/temp_jumpman.php
<?php // demo/temp_jumpman.php
/**
* Dealing with PHP nested arrays
*
* https://stackoverflow.com/questions/45145282/merge-two-arrays-by-specific-fields
*/
error_reporting(E_ALL);
echo '<pre>';
// TEST DATA CREATED FROM THE POST AT STACK - ID, Fruit, State
$first = Array(
'0' => [
'ID' => '1',
'Fruit' => 'Apple',
'State' => 'Ohio',
],
'1' => [
'ID' => '2',
'Fruit' => 'Orange',
'State' => 'Hawaii',
],
'2' => [
'ID' => '3',
'Fruit' => 'Orange',
'State' => 'Vermont',
],
);
// TEST DATA CREATED FROM THE POST AT STACK - ID, description, Price
$second = Array(
'0' => [
'ID' => '1',
'description' => 'This is sample description',
'Price' => '20',
],
'1' => [
'ID' => '1',
'description' => 'This is sample description 2',
'Price' => '15',
],
'2' => [
'ID' => '2',
'description' => 'This is the second description',
'Price' => '100',
],
'3' => [
'ID' => '2',
'description' => 'This is the second description 2',
'Price' => '50',
],
'4' => [
'ID' => '3',
'description' => 'This is the third description',
'Price' => '99',
],
);
$out = [];
foreach ($first as $arr)
{
// PLACEHOLDERS FOR THE FOUND DATA FROM THE SECOND ARRAY
$arr['description'] = [];
$arr['Price'] = [];
$id = $arr['ID']; // THE ID WE WANT IN THE SECOND ARRAY
foreach ($second as $idp)
{
if ($idp['ID'] == $arr['ID'])
{
$arr['description'][] = $idp['description'];
$arr['Price'][] = $idp['Price'];
}
}
$out[] = $arr;
}
print_r($out);

Remove array keys that aren't listed in a second array

The following is my result array
Array (
[0] => Array
(
[ProductID] => 220
[TextID] => 477
[ProductName] => Hugo Woman
[Price] => 43.91
[BTW] => 21
[Stock] => 500
[BrandID] => 186
[ProductImage] => https://media.douglas-shop.com/874229/300_0/Hugo_Boss-Hugo_Woman-EdP_30ml_GRATIS_Nail_Polish_4ml.jpg
[CategoryID] => 1
[SubCategoryID] => 1
[View] => 0
)
[1] => Array
(
[ProductID] => 616
[TextID] => 959
[ProductName] => Hugo XY
[Price] => 44.95
[BTW] => 21
[Stock] => 500
[BrandID] => 186
[ProductImage] => https://media.douglas-shop.com/333660/300_0/Hugo_Boss-Hugo_XY.jpg
[CategoryID] => 2
[SubCategoryID] => 2
[View] => 0
)
[2] => Array
(
[ProductID] => 650
[TextID] => 991
[ProductName] => Hugo Just Different
[Price] => 45.76
[BTW] => 21
[Stock] => 500
[BrandID] => 186
[ProductImage] => https://media.douglas-shop.com/617162/300_0/Hugo_Boss-Hugo_Just_Different.jpg
[CategoryID] => 2
[SubCategoryID] => 2
[View] => 0
)
)
I have a second array with subcategories, in which the key is referencing to the SubCategoryID:
Array
(
[1] => Array
(
[EN] => Ladies
[NL] => Dames
)
[2] => Array
(
[EN] => Men
[NL] => Heren
)
)
I want to loop through the result array and remove the keys who don't have a SubCategoryID listed in the second array. I looked at http://php.net/manual/en/function.array-filter.php, but can't figure out the best way to do this.
Thank you!
There are two solutions to the above problem, one with using simple for loop and one with using array_walk() function.
Here, $result_array is your result array and $subcategory_array is your subcategory array.
Solution(1):
$subcategory_ids = array_keys($subcategory_array);
$arrLength = count($result_array);
for($i = 0; $i < $arrLength; ++$i){
if(!in_array($result_array[$i]['SubCategoryID'], $subcategory_ids)){
unset($result_array[$i]);
}
}
// display $result_array
echo "<pre>"; print_r($result_array);
Solution(2):
$subcategory_ids = array_keys($subcategory_array);
function filter_arr($item, $key){
global $result_array, $subcategory_ids;
if(!in_array($item['SubCategoryID'], $subcategory_ids)){
unset($result_array[$key]);
}
}
array_walk($result_array, "filter_arr");
// display $result_array
echo "<pre>"; print_r($result_array);
Please try i thnik this help to you..
$array = array (
0 => array
(
'ProductID' => 220,
'TextID' => 477,
'ProductName' => 'Hugo Woman',
'Price' => 43.91,
'BTW' => 21,
'Stock' => 500,
'BrandID' => 186,
'ProductImage' => 'https://media.douglas-shop.com/874229/300_0/Hugo_Boss-Hugo_Woman-EdP_30ml_GRATIS_Nail_Polish_4ml.jpg',
'CategoryID' => 1,
'SubCategoryID' => 1,
'View' => 0
),
1 => array
(
'ProductID' => 616,
'TextID' => 959,
'ProductName' => 'Hugo XY',
'Price' => 44.95,
'BTW' => 21,
'Stock' => 500,
'BrandID' => 186,
'ProductImage' => 'https://media.douglas-shop.com/333660/300_0/Hugo_Boss-Hugo_XY.jpg',
'CategoryID' => 1,
'SubCategoryID' => 2,
'View' => 0
),
'2' => array
(
'ProductID' => 650,
'TextID' => 991,
'ProductName' => 'Hugo Just Different',
'Price' => 45.76,
'BTW' => 21,
'Stock' => 500,
'BrandID' => 186,
'ProductImage' => 'https://media.douglas-shop.com/617162/300_0/Hugo_Boss-Hugo_Just_Different.jpg',
'CategoryID' => 2,
'SubCategoryID' => 1,
'View' => 0
),);
$array1 = array (
1 => array
(
'EN' => 'Ladies',
'NL' => 'Dames'
),
2 => array
(
'EN' => 'Men',
'NL' => 'Heren'
),);
foreach($array as $newArray){
if (array_key_exists($newArray['SubCategoryID'], $array1)) {
echo '<pre>';
print_r($newArray);
echo '</pre>';}}

Group array rows by multiple column values and sum another column within each group

I'm trying to group the data in an array of associative arrays by three columns (year, month, grupo) and sum another column (quantity).
Given an array like:
$in = [
['year' => '2010', 'month' => '11', 'grupo' => '2', 'quantity' => 3],
['year' => '2010', 'month' => '11', 'grupo' => '3', 'quantity' => 4],
['year' => '2011', 'month' => '2', 'grupo' => '2', 'quantity' => 4],
['year' => '2011', 'month' => '2', 'grupo' => '2', 'quantity' => 4],
['year' => '2012', 'month' => '3', 'grupo' => '4', 'quantity' => 3]
['year' => '2012', 'month' => '3', 'grupo' => '4', 'quantity' => 3]
];
I want get:
[
['year' => '2010', 'month' => '11', 'grupo' => '2', 'quantity' => 3],
['year' => '2010', 'month' => '11', 'grupo' => '3', 'quantity' => 4],
['year' => '2011', 'month' => '2', 'grupo' => '2', 'quantity' => 8],
['year' => '2012', 'month' => '3', 'grupo' => '4', 'quantity' => 6]
]
I've tried something like this:
$out = array();
foreach ($in as $row) {
if (!isset($out[$row['year']['month']['grupo']])) {
$out[$row['year']['month']['grupo']] = array(
'year' => $row['year'],
'month' => $row['month'],
'grupo' => $row['grupo'],
'quantity' => 0,
);
}
$out[$row['year']['month']['grupo']]['quantity'] += $row['quantity'];
}
$out = array_values($out);
but it fails while trying to group the 3 fields.
I think the earlier answers overlooked the desired result -- the solutions from #hellcode and #Rasclatt create unnecessarily deep structures.
The coding attempt in the question was very close to being right, there was only a flaw in generating unique grouping keys in the first level.
To generate unique grouping keys, you must forge a string from the multiple identifying values in the row. In other words, "compose" a unique value from the three targeted column values -- a composite key.
Code: (Demo)
$result = [];
foreach ($in as $row) {
$compositeKey = implode(array_slice($row, 0, 3));
if (!isset($result[$compositeKey])) {
$result[$compositeKey] = $row;
} else {
$result[$compositeKey]['quantity'] += $row['quantity'];
}
}
var_export(
array_values($result)
);
Try this:
$out = array();
foreach ($in as $row) {
if(! isset($out[$row['year']][$row['month']][$row['grupo']])) {
$out[$row['year']][$row['month']][$row['grupo']]=0;
}
$out[$row['year']][$row['month']][$row['grupo']] += $row['quantity'];
}
print_r($out);
It will output your desired values, but as a multidimensional value array, not as a flat array with key => value pairs:
Array
(
[2010] => Array
(
[11] => Array
(
[2] => 3
[3] => 4
)
)
[2011] => Array
(
[2] => Array
(
[2] => 8
)
)
[2012] => Array
(
[3] => Array
(
[4] => 6
)
)
)
But you can rearrange your array:
$out2 = array();
foreach($out as $year => $year_array) {
foreach($year_array as $month => $month_array) {
foreach($month_array as $grupo => $quantity) {
$out2[] = array('year' => $year, 'month' => $month, 'grupo' => $grupo, 'quantity' => $quantity);
}
}
}
print_r($out2);
This will output:
Array
(
[0] => Array
(
[year] => 2010
[month] => 11
[grupo] => 2
[quantity] => 3
)
[1] => Array
(
[year] => 2010
[month] => 11
[grupo] => 3
[quantity] => 4
)
[2] => Array
(
[year] => 2011
[month] => 2
[grupo] => 2
[quantity] => 8
)
[3] => Array
(
[year] => 2012
[month] => 3
[grupo] => 4
[quantity] => 6
)
)
This will retain values and also give sum.
foreach($in as $row) {
$out[$row['year']][$row['month']][$row['grupo']]['quantity'][] = $row['quantity'];
$out[$row['year']][$row['month']][$row['grupo']]['sum'] = array_sum($out[$row['year']][$row['month']][$row['grupo']]['quantity']);
}
print_r($out);
GIVES
Array
(
[2010] => Array
(
[11] => Array
(
[2] => Array
(
[quantity] => Array
(
[0] => 3
)
[sum] => 3
)
[3] => Array
(
[quantity] => Array
(
[0] => 4
)
[sum] => 4
)
)
)
[2011] => Array
(
[2] => Array
(
[2] => Array
(
[quantity] => Array
(
[0] => 4
[1] => 4
)
[sum] => 8
)
)
)
[2012] => Array
(
[3] => Array
(
[4] => Array
(
[quantity] => Array
(
[0] => 3
[1] => 3
)
[sum] => 6
)
)
)
)

How separate php array with same value and not same

I have a shop basket with for example 6 items. Some items are for one shop and another items for one and maybe two shops.
I want create factors for each shops. How can I do? How can I known these items in basket are for one shop or has for 2 or 3 shop . How can separate this items to factor.
Array('customer' => Array('basket' => Array(
'9_2' => Array
(
"row" => "0",
'item' => 'cd',
'count' => '1',
'sale_start_date' => '1391-12-25 19:27:56',
'sale_end_date' => '1392-04-20 19:27:49',
'sale_price' => '40500',
'price' => '54564',
'id' => '999035',
'shopid' => '4'
),
'999_17' => Array
(
'row' => '1',
'item' => 'car',
'count' => '1',
'sale_start_date' => '0000-00-00 00:00:00',
'sale_end_date' => '0000-00-00 00:00:00',
'sale_price' => '0',
'price' => '520000',
'id' => '999039',
'code' => 'b125nh',
'shopid' => '6'
),
'9_3' => Array
(
'row' => '2',
'item' => 'book',
'count' => '1',
'sale_start_date' => '0000-00-00 00:00:00',
'sale_end_date' => '0000-00-00 00:00:00',
'sale_price' => '0',
'price' => '520000',
'id' => '999039',
'code' => 'b125nh',
'shopid' => '4'
),
'10_5' => Array
(
'row' => '2',
'item' => 'dvd',
'count' => '1',
'sale_start_date' => '0000-00-00 00:00:00',
'sale_end_date' => '0000-00-00 00:00:00',
'sale_price' => '0',
'price' => '520000',
'id' => '999039',
'code' => 'b125nh',
'shopid' => '5'
)
)
)
);
This example is array from my SESSION . I want seperate factor with shopid value. In this basket for example we have 2 item from shopid=4 and have 1 item from shopid=6 and one item from shopid=5 how can create seprate factor for each shop.
First I use usort function for sort array with shopid but I can't continue for separate each same and not same item shop for create factor
Something like this should work
<?php
$shopItems = array();
foreach ($_SESSION['customer']['basket'] as $basket) {
$key = $basket['shopid'];
$shopItems[$key][] = $basket;
}
This will store groups of items from the same shop id in elements of the array $shopItems
For example (only showing shop id 4)
Array (
[4] => Array (
[0] => array(
"row" => "0",
'item' => 'cd',
'count' => '1',
'sale_start_date' => '1391-12-25 19:27:56',
'sale_end_date' => '1392-04-20 19:27:49',
'sale_price' => '40500',
'price' => '54564',
'id' => '999035',
'shopid' => '4'
),
[1] => array(
'row' => '2',
'item' => 'book',
'count' => '1',
'sale_start_date' => '0000-00-00 00:00:00',
'sale_end_date' => '0000-00-00 00:00:00',
'sale_price' => '0',
'price' => '520000',
'id' => '999039',
'code' => 'b125nh',
'shopid' => '4'
)
)
)
$basket = array();
foreach ($_SESSION['customer']['basket'] as $k => $v)
$basket[$v['shopid']][$k] = $v;
print_r($basket);
Result:
Array
(
[4] => Array
(
[9_2] => Array
(
[row] => 0
[item] => cd
[count] => 1
[sale_start_date] => 1391-12-25 19:27:56
[sale_end_date] => 1392-04-20 19:27:49
[sale_price] => 40500
[price] => 54564
[id] => 999035
[shopid] => 4
)
[9_3] => Array
(
[row] => 2
[item] => book
[count] => 1
[sale_start_date] => 0000-00-00 00:00:00
[sale_end_date] => 0000-00-00 00:00:00
[sale_price] => 0
[price] => 520000
[id] => 999039
[code] => b125nh
[shopid] => 4
)
)
[6] => Array
(
[999_17] => Array
(
[row] => 1
[item] => car
[count] => 1
[sale_start_date] => 0000-00-00 00:00:00
[sale_end_date] => 0000-00-00 00:00:00
[sale_price] => 0
[price] => 520000
[id] => 999039
[code] => b125nh
[shopid] => 6
)
)
[5] => Array
(
[10_5] => Array
(
[row] => 2
[item] => dvd
[count] => 1
[sale_start_date] => 0000-00-00 00:00:00
[sale_end_date] => 0000-00-00 00:00:00
[sale_price] => 0
[price] => 520000
[id] => 999039
[code] => b125nh
[shopid] => 5
)
)
)
This should do the trick.
function get_seperated_shops($all_items)
{
$seperated_shops = array();
foreach($all_items AS $item => $properties)
{
$seperated_shops[$properties['shopid']][$item] = $properties;
}
return $seperated_shops;
}
echo "<pre>";
print_r(get_seperated_shops($_SESSION['customer']['basket']));
echo "</pre>";

Categories