PHP create array based on date - php

I'm trying to create an dynamic array sorted on date. Let me try to explain. I've the follow user array
$users = [
0 => [
'user_id' => 1,
'user_date' => '2017-04-26',
'user_name' => 'test',
],
1 => [
'user_id' => 2,
'user_date' => '2017-04-26',
'user_name' => 'test 2',
],
2 => [
'user_id' => 3,
'user_date' => '2017-04-28',
'user_name' => 'test 3',
]
];
While looping throug this array a want to group the users that has the same date. An example how the output should look like
Array
(
[0] => Array
(
[DATE] => 2017-04-26
[USERS] => Array
(
[0] => Array
(
[user_id] => 1
[user_title] => test
)
[1] => Array
(
[user_id] => 2
[user_title] => test 2
)
)
)
[1] => Array
(
[DATE] => 2017-04-28
[USERS] => Array
(
[0] => Array
(
[user_id] => 4
[user_title] => test 4
)
)
)
)
I have tried to do some things in a foreach loop but could not make this get to work.
$result = array();
$i = 0;
// Start loop
foreach ($users as $user) {
// CHECK IF DATE ALREADY EXISTS
if(isset($result[$i]['DATE']) && $result[$i]['DATE'] == $user['user_date']){
$i++;
}
// FILL THE ARRAY
$result[$i] = [
'DATE' => $user['user_date'],
'USERS' => [
'user_id' => $user['user_id'],
'user_title' => $user['user_name'],
]
];
}
I've changed it a little bit to this:
foreach ($users as $user => $properties) {
foreach ($properties as $property => $value) {
if($property == 'user_date'){
if(empty($result[$value])){
$result[$i] = [];
}
$result[$i][] = [
'user_id' => $properties['user_id'],
'user_name' => $properties['user_name'],
];
$i++;
}
}
}
But how could i change the start keys (dates) to numbers equal to 0, 1 etc.

$users = [
0 => [
'user_id' => 1,
'user_date' => '2017-04-26',
'user_name' => 'test',
],
1 => [
'user_id' => 2,
'user_date' => '2017-04-26',
'user_name' => 'test 2',
],
2 => [
'user_id' => 3,
'user_date' => '2017-04-28',
'user_name' => 'test 3',
]
];
$sorted = [];
foreach ($users as $user => $properties) {
foreach ($properties as $property => $value) {
if ($property =='user_date') {
if (empty($sorted[$value])) {
$sorted[$value] = [];
}
$sorted[$value][] = $users[$user];
}
}
}
var_dump($sorted);
Do a nested loop through your arrays and then check for the unique value you're looking for (in this case the user_date) and add that as a key in your sorted array. If the key exists add a new item (user) to that key, otherwise make the new key first. This way you have an array of dates each containing an array of users with that date.

If you want the exact output you showed (honestly, I like Ryan's answer better):
$result = array();
$i = 0;
// Start loop
foreach ($users as $user) {
// CHECK IF DATE ALREADY EXISTS AND IS NOT IN THE SAME GROUP
if (isset($result[$i]['DATE']) && $result[$i]['DATE'] != $user['user_date']){
$i++;
}
// STARTING A NEW GROUP
if(!isset($result[$i])) {
$result[$i] = array(
'DATE' => $user['user_date'],
'USERS' => array()
);
}
// FILL THE ARRAY (note the ending [] to add a new entry in this group's USERS array)
$result[$i]['USERS'][] = array(
'user_id' => $user['user_id'],
'user_title' => $user['user_name'],
);
}

There are few ways to tackle your question. I always prefer to use PHP built-in function, as there are a lot of them. This answer uses a PHP builtin function usort to sort your array in place. It takes two arguments, you array and a comparator function. usort will parse two array object to comparator function. If you dont know about compactor functions, a Comparator compare these two objects and return a integer 1, 0, or -1 which tells if first object is greater, equal or less than second object, respectively. So pass in a comparator function to that takes care of the comparation of dates.
$users = [
0 => [
'user_id' => 1,
'user_date' => '2017-04-25',
'user_name' => 'test',
],
1 => [
'user_id' => 2,
'user_date' => '2017-04-26',
'user_name' => 'test 2',
],
2 => [
'user_id' => 3,
'user_date' => '2017-04-28',
'user_name' => 'test 3',
],
3 => [
'user_id' => 4,
'user_date' => '2017-04-28',
'user_name' => 'test 4',
],
4 => [
'user_id' => 5,
'user_date' => '2017-04-26',
'user_name' => 'test 5',
],
];
usort($users, function($user1, $user2){
// This function sort users by ascending order of date. Compares date. if user 1 has later date than user 2, place him on the bottom of the array
return strtotime($user1['user_date']) > strtotime($user2['user_date']);
});
var_dump($users);

Related

Unset array by key and value using PHP

My array are $arrIncome and $arrExpense. They have some the same date and some not the same date.
$arrIncome = [
[
'date' => '01-01-2019',
'total' => '500',
],
[
'date' => '02-01-2019',
'total' => '200',
],
[
'date' => '03-01-2019',
'total' => '300',
],
[
'date' => '04-01-2019',
'total' => '900',
],
];
$arrExpense= [
[
'date' => '01-01-2019',
'total' => '50',
],
[
'date' => '02-01-2019',
'total' => '60',
],
[
'date' => '07-01-2019',
'total' => '25',
],
[
'date' => '08-01-2019',
'total' => '50',
],
];
I loop in $arrIncome array, if I found income date have in $arrExpense array, I will remove an array in $arrExpense by income date of $arrIncome, because I want to make unique date.
foreach ($arrIncome as $income){
$isExistExpense = array_filter($arrExpense, function($expense) use($income){
return $expense->date == date('Y-m-d', strtotime($income->date));
});
if(count($isExistExpense) > 0 ){
foreach ($isExistExpense as $expense){
// THIS PLACE TO UNSET $arrExpense by date value
unset($arrExpense['date'] = $income->date); // this is a wrong way
}
}else{
// my code more here.....
}
}
You must unset it by the index.
You can do it like:
// Get the intersection of the dates
$isExistExpense = array_intersect(
array_column($arrIncome,'date'),
array_column($arrExpense,'date'));
// Loop through the `$arrExpense` and unset the that exist in the array.
foreach($arrExpense as $index=>$vals){
if(in_array($vals['date'], $isExistExpense)){
unset($arrExpense[$index]);
}
}
Hope this helps,
You can use array_filter to directly remove the elements of $arrExpense that have dates which exist in $arrIncome (using array_column to get the list of dates in that array):
$arrExpense = array_filter($arrExpense, function ($v) use ($arrIncome) {
return !in_array($v['date'], array_column($arrIncome, 'date'));
});
print_r($arrExpense);
Output:
Array (
[2] => Array ( [date] => 07-01-2019 [total] => 25 )
[3] => Array ( [date] => 08-01-2019 [total] => 50 )
)
Demo on 3v4l.org

Group/Merge rows from two 2d arrays based on 3 identifying columns and fill missing column values with null

I'm need to merge two 2d arrays by their time, size, and type values. This should created grouped data where value_one and value_two elements may exist in the same row. If there aren't two rows to merge together, then I need the missing element to be set to null -- this way all rows will have the same elements/structure.
$array1 = [
[
'date' => '2018-06-23',
'size' => 'L',
'type' => 'shoes',
'value_one' => '66',
],
[
'date' => '2018-06-23',
'size' => 'XL',
'type' => 'shirt',
'value_one' => '43',
],
[
'date' => '2018-06-23',
'size' => 'M',
'type' => 'Bag',
'value_one' => '23',
]
];
And
$array2 = [
[
'date' => '2018-06-23',
'size' => 'L',
'type' => 'shoes',
'value_two' => '28',
],
[
'date' => '2018-06-23',
'size' => 'XL',
'type' => 'shirt',
'value_two' => '56',
],
[
'date' => '2018-06-23',
'size' => 'M',
'type' => 'Bag',
'value_two' => '14',
],
[
'date' => '2018-06-23',
'size' => 'S',
'type' => 'Cap',
'value_two' => '29',
]
]
Desired result:
[
[
'date' => '2018-06-23',
'size' => 'L',
'type' => 'shoes',
'value_one' => '66',
'value_two' => '28',
],
[
'date' => '2018-06-23',
'size' => 'XL',
'type' => 'shirt',
'value_one' => '43',
'value_two' => '56',
],
[
'date' => '2018-06-23',
'size' => 'M',
'type' => 'Bag',
'value_one' => '23',
'value_two' => '14',
],
[
'date' => '2018-06-23',
'size' => 'S',
'type' => 'Cap',
'value_one' => null,
'value_two' => '29',
]
]
I want to solve this case with php, laravel or collection "Laravel" class.
I tried to create the array and merge using array_merge_recursive(), array_merge(), or using this code:
foreach ($d as $k => $v) {
$new_arr[$v['date']][] = $v;
}
try
//both arrays will be merged including duplicates
$result = array_merge( $array1, $array2 );
//duplicate objects will be removed
$result = array_map("unserialize", array_unique(array_map("serialize", $result)));
//array is sorted on the bases of id
sort( $result );
For an elegant solution that only needs one loop, use the following:
Hardcode an array of default keys in your desired order.
Merge the arrays and iterate.
Identifying matching data sets by the first three elements in each row.
Depending on whether the composite key has been encountered before, overwrite the default or cached data with the current row.
To remove temporary composite key after looping, call array_values() on the result array.
Code: (Demo)
$defaults = array_fill_keys(['date', 'size', 'type', 'value_one', 'value_two'], null);
$result = [];
foreach (array_merge($array1, $array2) as $row) {
$compositeKey = implode('_', array_slice($row, 0, 3));
$result[$compositeKey] = array_merge($result[$compositeKey] ?? $defaults, $row);
}
var_export(array_values($result));
You can try this
$Array_final= [];
foreach ($Array_one as $key1 => $value1) {
foreach ($Array_two as $key2 => $value2) {
if ($value1['date']==$value2['date']) {
$Array_final[]=$value2+$value1;
}
}
}
You can try this :-
$final = $arr1; // default get all values from first array
foreach ($arr2 as $value) { // loop through second array to match
$flag = 0;
foreach ($final as $key => $data) {
// Check for date, size and type
if ($data['date']===$value['date'] && $data['size']===$value['size'] && $data['type']===$value['type']) {
$final[$key]['value_two'] = $value['value_two'];
$flag = 1;
break;
}
}
if ($flag === 0) { // If similar not found, then add new one
array_push($final, $value);
}
}
print_r($final);
Output :-
Array
(
[0] => Array
(
[date] => 2018-06-23
[size] => L
[type] => shoes
[value_one] => 66
[value_two] => 28
)
[1] => Array
(
[date] => 2018-06-23
[size] => XL
[type] => shirt
[value_one] => 43
[value_two] => 56
)
[2] => Array
(
[date] => 2018-06-23
[size] => M
[type] => Bag
[value_one] => 23
[value_two] => 14
)
[3] => Array
(
[date] => 2018-06-23
[size] => S
[type] => Cap
[value_two] => 29
)
)
Fiddle link :- https://3v4l.org/fSh1V
try
var result = a1.slice(0);
for (var i = 0 ; i < result.length ; i++){
for (var j = 0; j < a2.length ; j++){
if (result[i]. date == a2[j]. date && result[i]. size == a2[j]. size && result[i]. type == a2[j]. type){
result[i]. value_one = a2[j]. value_one;
result[i]. value_two = a2[j].value_two;
}
};
};
console.log(result);

Counting occurrences in an array that has more than 1 key

I'm trying to get the occurrences of an array taking in count 1 key value, for example:
$newarray[0] = [
'id' => '2',
'date' => '2016-04-22'
];
$newarray[1] = [
'id' => '2',
'date' => '2016-04-13'
];
$newarray[2] = [
'id' => '2',
'date' => '2016-04-12'
];
$newarray[3] = [
'id' => '1',
'date' => '2016-03-11'
];
$newarray[4] = [
'id' => '2',
'date' => '2016-03-05'
];
$newarray[5] = [
'id' => '1',
'date' => '2016-03-01'
];
I want to transform this, to something like this:
Array ( [0] => Array ( [id] => 1 [date] => 2016-03-11 [occurences] => 2 ) [1] => Array ( [id] => 2 [date] => 2016-04-22 [occurences] => 4 ) )
I tried doing this:
$cleanarray;
$newarray2=$newarray;
$newarray;
$k=0;
$num=1;
for($i=0; $i<count($newarray); $i++){
for($j=1; $j<count($newarray2); $j++){
if($newarray2[$j]["id"]==$newarray[$i]["id"]){
$num++;
}
}
$cleanarray[$k] = [
'id' => $newarray[$i]["id"],
'date' => $newarray[$i]["date"],
'occurences' => $num
];
$k++;
$num=0;
}
But a lot of items repeat, with the same occurrences but several times, and in other cases the repeated items (with same id) would have different occurrences, so I don't know what can I do, I know that there is a function of:
$occurences = array_count_values($array);
But it doesn't work in this case, how can I approach to the solution?
I know what are you looking for, but I think this could solve your problems:
$newarray[0] = [
'id' => '2',
'date' => '2016-04-22'
];
$newarray[1] = [
'id' => '2',
'date' => '2016-04-12'
];
$newarray[2] = [
'id' => '2',
'date' => '2016-04-12'
];
$newarray[3] = [
'id' => '1',
'date' => '2016-03-11'
];
$newarray[4] = [
'id' => '2',
'date' => '2016-03-05'
];
$newarray[5] = [
'id' => '1',
'date' => '2016-03-01'
];
foreach($newarray as $key => $value){
if(isset($found[$value['id']][$value['date']])) {
$found[$value['id']][$value['date']]++;
} else {
$found[$value['id']][$value['date']] = 1;
}
}
print_r($found);
this will return something like:-
Array
(
[2] => Array
(
[2016-04-22] => 1
[2016-04-12] => 2
[2016-03-05] => 1
)
[1] => Array
(
[2016-03-11] => 1
[2016-03-01] => 1
)
)
Using temporary keys for this process will be the most performant way. Temporary keys simplify the output array task, requiring less and faster checking. If you wish to sort on id after the result array is generated, the temporary keys allow a simple ksort() call.
Code: (Demo)
$newarray=[
['id' => '2','date' => '2016-04-22'],
['id' => '2','date' => '2016-04-13'],
['id' => '2','date' => '2016-04-12'],
['id' => '1','date' => '2016-03-11'],
['id' => '2','date' => '2016-03-05'],
['id' => '1','date' => '2016-03-01']
];
foreach($newarray as $a){
if(!isset($result[$a['id']])){
$result[$a['id']]=array_merge($a,['occurrences'=>1]); // use id as temp key, preserve first found date
}else{
++$result[$a['id']]['occurrences']; // only update occurrences to preserve date
}
}
ksort($result); // optionally sort on id ASC
var_export(array_values($result)); // remove temporary keys from first level and print to screen
Output:
array (
0 =>
array (
'id' => '1',
'date' => '2016-03-11',
'occurrences' => 2,
),
1 =>
array (
'id' => '2',
'date' => '2016-04-22',
'occurrences' => 4,
),
)
You can do it like below:-
$final_array = array();
foreach($newarray as $arr){
if(!in_array($arr['id'],array_keys($final_array))){
$final_array[$arr['id']] = $arr;
$final_array[$arr['id']]['occurences'] = 1;
}else{
$final_array[$arr['id']]['occurences'] += 1;
}
}
$final_array= array_values($final_array);
print_r($final_array);
Output:- https://eval.in/847242
Note:- if you want final array to be ascending order of id then use usort() function like below:-
function cmpId($a, $b) {
return ($a['id'] - $b['id']);
}
usort($final_array, "cmpId");
print_r($final_array);
Output:- https://eval.in/847245

Sorting array in PHP based on another array indexes

I have two arrays
// array of objects
$records = array(
[0] => (object) [
'id' => 1, // (*)
....
],
[1] => (object) [
'id' => 2, // (*)
....
],
[2] => (object) [
'id' => 3, // (*)
....
],
);
// array 2
// the keys in this array refer to the object ids (*)
$sorted = array(
'2' => 7,
'3' => 4,
'1' => 2,
);
$new_records = array();
What I want to do is to sort the values of first array (i.e the objects) based on the order of the key index of the second array, so the end result in this case will become:
$new_records = array(
[0] => (object) [
'id' => 2,
....
],
[1] => (object) [
'id' => 3,
....
],
[2] => (object) [
'id' => 1,
....
],
);
$records = $new_records;
Try this
$new_records = array();
foreach( $sort as $id => $pos ) {
foreach( $records as $record ) {
if( $record[ 'id' ] == $id ) {
$new_records[] = $record;
break;
}
}
}
This make the job
$records = array(
0 => (object) [
'id' => 1, // (*)
],
1 => (object) [
'id' => 2, // (*)
],
2 => (object) [
'id' => 3, // (*)
],
);
// array 2
// the keys in this array refer to the object ids (*)
$sorted = array(
'2' => 7,
'3' => 4,
'1' => 2,
);
$keySorted = array_keys($sorted);
usort($records, function ($a, $b) use ($keySorted) {
$pos_a = array_search($a->id, $keySorted);
$pos_b = array_search($b->id, $keySorted);
return $pos_a - $pos_b;
});
var_dump($records);
Here, I have created sorting of array and add to your array of object using current() and key() is from php.
$i = 0;
while ($value = current($sorted)) {
$key = key($sorted); // get key from array 2
$records[i]->array('id' => $key); // set key to array of object
next($array);
$i++;
}
I hope this may help you.
Code: (Demo)
$records = [(object)['id' => 1], (object)['id' => 2], (object)['id' => 3]];
$sorted = ['2' => 7, '3' => 4, '1' => 2];
$tempArr = array();
foreach ($records as $value) {
$tempArr[$value->id] = $value;
}
$resultArr = array_values(array_replace($sorted, $tempArr));
var_export($resultArr);
Output:
array (
0 =>
stdClass::__set_state(array(
'id' => 2,
)),
1 =>
stdClass::__set_state(array(
'id' => 3,
)),
2 =>
stdClass::__set_state(array(
'id' => 1,
)),
)

php multidimensional array get values

This is my array in php $hotels
Array
(
[0] => Array
(
[hotel_name] => Name
[info] => info
[rooms] => Array
(
[0] => Array
(
[room_name] => name
[beds] => 2
[boards] => Array
(
[board_id] => 1
[price] =>200.00
)
)
)
)
)
How can I get board_id and price I have tried few foreach loops but can't get the result
foreach($hotels as $row)
{
foreach($row as $k)
{
foreach($k as $l)
{
echo $l['board_id'];
echo $l['price'];
}
}
}
This code didn't work.
This is the way to iterate on this array:
foreach($hotels as $row) {
foreach($row['rooms'] as $k) {
echo $k['boards']['board_id'];
echo $k['boards']['price'];
}
}
You want to iterate on the hotels and the rooms (the ones with numeric indexes), because those seem to be the "collections" in this case. The other arrays only hold and group properties.
For people who searched for php multidimensional array get values and actually want to solve problem comes from getting one column value from a 2 dimensinal array (like me!), here's a much elegant way than using foreach, which is array_column
For example, if I only want to get hotel_name from the below array, and form to another array:
$hotels = [
[
'hotel_name' => 'Hotel A',
'info' => 'Hotel A Info',
],
[
'hotel_name' => 'Hotel B',
'info' => 'Hotel B Info',
]
];
I can do this using array_column:
$hotel_name = array_column($hotels, 'hotel_name');
print_r($hotel_name); // Which will give me ['Hotel A', 'Hotel B']
For the actual answer for this question, it can also be beautified by array_column and call_user_func_array('array_merge', $twoDimensionalArray);
Let's make the data in PHP:
$hotels = [
[
'hotel_name' => 'Hotel A',
'info' => 'Hotel A Info',
'rooms' => [
[
'room_name' => 'Luxury Room',
'bed' => 2,
'boards' => [
'board_id' => 1,
'price' => 200
]
],
[
'room_name' => 'Non Luxy Room',
'bed' => 4,
'boards' => [
'board_id' => 2,
'price' => 150
]
],
]
],
[
'hotel_name' => 'Hotel B',
'info' => 'Hotel B Info',
'rooms' => [
[
'room_name' => 'Luxury Room',
'bed' => 2,
'boards' => [
'board_id' => 3,
'price' => 900
]
],
[
'room_name' => 'Non Luxy Room',
'bed' => 4,
'boards' => [
'board_id' => 4,
'price' => 300
]
],
]
]
];
And here's the calculation:
$rooms = array_column($hotels, 'rooms');
$rooms = call_user_func_array('array_merge', $rooms);
$boards = array_column($rooms, 'boards');
foreach($boards as $board){
$board_id = $board['board_id'];
$price = $board['price'];
echo "Board ID is: ".$board_id." and price is: ".$price . "<br/>";
}
Which will give you the following result:
Board ID is: 1 and price is: 200
Board ID is: 2 and price is: 150
Board ID is: 3 and price is: 900
Board ID is: 4 and price is: 300

Categories