I have an array in php like this :
$multid_array = array(
"url" => "www.checkmyhouse.cpm",
"date" => "2019/12/12",
"minor" => 1,
"sittingroom" => 1,
"dinningroom" => 2,
"toilet" => 2,
"parking" => 1,
"bedroom" => 2,
"garage" => 2,
"rooms" => 4,
"garden" => 1,
"url_1" => "-sameurl-",
"date_1" => "2019/12/3",
"minor_1" => 3,
"sittingroom_1" => 2,
"dinningroom_1" => 2,
"toilet_1" => 3,
"parking_1" => 1,
"bedroom_1" => 2,
"garage_1" => 6,
"rooms_1" => 6,
"garden_1" => 1,
"url_2" => "-sameurl-",
"date_2" => "2019/12/5",
"minor_2" => 3,
"sittingroom_2" => 2,
"dinningroom_2" => 2,
"toilet_2" => 3,
"parking_2" => 1,
"bedroom_2" => 5,
"garage_2" => 6,
"rooms_2" => 9,
"garden_2" => 1,
);
I have searched around, found this link. but not been able to figure it out. keep getting close.
array_slice in multidimensional array?
This is the output I would like:
$array =
[
"levels" => array(
"0" => array(
"url" => "www.checkmyhouse.cpm",
"date" => "2019/12/1",
"minor" => 1,
"sittingroom" => 1,
"dinningroom" => 2,
"toilet" => 2,
"parking" => 1,
"bedroom" => 2,
"garage" => 2,
"rooms" => 5,
"garden" => 1,
),
"1" => array(
"url" => "-sameurl-",
"date" => "2019/12/3",
"minor" => 3,
"sittingroom" => 2,
"dinningroom" => 2,
"toilet" => 3,
"parking" => 1,
"bedroom" => 2,
"garage" => 6,
"rooms" => 6,
"garden" => 1,
),
"2" => array(
"url" => "-sameurl-",
"date" => "2019/12/5",
"minor" => 3,
"sittingroom" => 2,
"dinningroom" => 2,
"toilet" => 3,
"parking" => 1,
"bedroom" => 5,
"garage" => 6,
"rooms" => 9,
"garden" => 1,
)
)
];
Just trying to rearrange it. but I have used array_slice and could only get the output of the first 9 elements.
array_splice($multid_array,9);
But I want to run it automatically, so in case more information gets added into the array then it would still work
Why not use simple for loop: (in this case you can have various number of field in each array and they don't need to be fixed as when use array_chunk)
$multid_array = array("url" => "www.checkmyhouse.cpm","date" => "2019/12/12","url_1" => "-sameurl-","date_1" => "2019/12/3","url_2" => "-sameurl-","date_2" => "2019/12/5",);
$ans = [];
foreach($multid_array as $k => $v) {
$parts = explode("_", $k);
$pk = 0; //default as 0 as when no prefix set to key "0"
if (count($parts) > 1) { // check if has suffix
$pk = $parts[1];
$k = $parts[0];
}
if (!isset($ans[$pk]))
$ans[$pk] = []; // init array if first time
$ans[$pk][$k] = $v;
}
Now $ans will contain your data - you can add "levels" key if you wish.
This will only works if you have "_" saved to mark inner indexes and they are not used in the actual keys
Related
Is there a chance to array_slice is bugged (using PHP 8.0.12)
I were looking for best way to get few elements(limited) of array with possible offset so tried to array_slice but its keep return me wrong index then i expect
I have array with objects from database and they looks like(ill write only id)
$questions simplified to only id
$limit = 1;
$questions = array(
array(
'id' => 2,
'stage' => 1,
'question_order' => 0,
'many_answers' => 0,
'points' => 5.5,
'spread_points_in_time' => 0,
'question' => "Czy Johnny Deep grał Jack'a Sparow'a?",
'time' => "00:00:10"
),
array(
'id' => 3,
'stage' => 1,
'question_order' => 0,
'many_answers' => 0,
'points' => 4.5,
'spread_points_in_time' =>0,
'question' => "Producent laptopa Darka",
'time' => "00:00:00"
),
array(
'id' => 1,
'stage' => 1,
'question_order' => 0,
'many_answers' => 0,
'points' => 10,
'spread_points_in_time' => 0,
'question' => "Która klawiatura jest mechniczna",
'time' => "00:00:10"
),
array(
'id' => 8,
'stage' => 2,
'question_order' => 0,
'many_answers' => 0,
'points' => 30,
'spread_points_in_time' => 1,
'question' => "2*2",
'time' => "00:00:30"
),
array(
'id' => 4,
'stage' => 2,
'question_order' => 0,
'many_answers' => 0,
'points' => 30,
'spread_points_in_time' => 0,
'question' => "Który język programowania ma dostęp do komórek pamięci komputera?",
'time' => "00:00:30"
),
array(
'id' => 7,
'stage' => 2,
'question_order' => 0,
'many_answers' => 0,
'points' => 30,
'spread_points_in_time' => 0,
'question' => "2+2",
'time' => "00:00:30"
),
array(
'id' => 10,
'stage' => 3,
'question_order' => 1,
'many_answers' => 1,
'points' => 5,
'spread_points_in_time' => 0,
'question' => "Jaki jest symbol chemiczny srebra?",
'time' => "00:00:00"
),
array(
'id' => 11,
'stage' => 3,
'question_order' => 0,
'many_answers' => 1,
'points' => 5,
'spread_points_in_time' => 0,
'question' => "Jaka jest żywotność ważki?",
'time' => "00:00:00"
),
array(
'id' => 9,
'stage' => 3,
'question_order' => 0,
'many_answers' => 0,
'points' => 5,
'spread_points_in_time' => 0,
'question' => "W którym roku Titanic zatonął na Oceanie Atlantyckim 15 kwietnia podczas dziewiczej podróży z Southampton?",
'time' => "00:00:00"
)
);
echo json_encode(
array(
'all' => $questions,
'limit' => $limit,
'sliced' => array_slice($questions, 0, $limit),
)
);
so when i try array_splice(array, 0, 1) i would expect 1 so id should be 2 but instead i get object which have id 1
i also tried with flag to keep indexed but then i end up same but with true index of object with id 1 (then key is 2)
If i put limit as 2 then i get object with id 1 and also object with id 2 (flag to keep indexed also return me properly to objects 2 and 0)
Also tried to remove id from every object by
foreach($questions as $key => $question)
{
unset($questions[$key]['id'];
}
But this didnt changed anything
$questions source https://pastebin.com/wDfJdm9Z
After plenty of combinations i figured it out
I were sorting this array before everything with forcing keys
So in sorting it looked like
foreach($toSort as $key => $item)
{
foreach($ids as $idKey => $id)
{
if($item['id'] == $id)
{
$sorted[$idKey] = $item;
break;
}
}
}
So for example array could end up with wrong order of keys like:
array(
[1] => item2,
[0] => item1,
[2] => item3
);
I were expecting array gona shove key 0 to be index 0 but don't looks like
Setting something to exact key isn't same as set something to set at exact index
SOLUTION WAS add ksort($sorted) before return $sorted
I have to make the array to unique array list if the invoice_products_id is same and for the same invoice_products_id i have add the amount. I am able to make it unique but amount is not adding.
0 =>{
'id' => 9,
'invoice_products_id' => 2,
'amount' => 1.8,
},
1 =>{
'id' => 10,
'invoice_products_id' => 3,
'amount' => 2,
},
2 =>{
'id' => 11,
'invoice_products_id' => 2,
'amount' => 1.1,
},
3 =>{
'id' => 12,
'invoice_products_id' => 3,
'amount' => 1.2,
},
code:
$invtax=[];
foreach($invoiceProduct['invoice_taxes'] as $taxkey=>$taxval){
$ref=$taxval->invoice_products_id;
if(isset($invtax[$ref])){
$invtax[$ref]->amount+=$taxval->amount;
}else{
$invtax[$ref]=$taxval;
}
}
result:
2 =>{
'id' => 11,
'invoice_products_id' => 2,
'amount' => 2.9,
},
3 =>{
'id' => 12,
'invoice_products_id' => 3,
'amount' => 1.2,
},
expected:
2 =>{
'id' => 11,
'invoice_products_id' => 2,
'amount' => 2.9,
},
3 =>{
'id' => 12,
'invoice_products_id' => 3,
'amount' => 3.2,
},
Making use of array_filter and array_walk functions
See here for live example: https://3v4l.org/rXXR9
Input
<?php
$arr = [
[
'id' => 9,
'invoice_products_id' => 2,
'amount' => 1.8,
],[
'id' => 10,
'invoice_products_id' => 3,
'amount' => 2,
],[
'id' => 11,
'invoice_products_id' => 2,
'amount' => 1.1,
],[
'id' => 12,
'invoice_products_id' => 3,
'amount' => 1.2,
],
];
Program
<?php
$assorted_heap = [];
$filter_function = function($v, $k) {
global $assorted_heap;
if (isset($assorted_heap[$v['invoice_products_id']])) {
$assorted_heap[$v['invoice_products_id']][1] += $v['amount'];
return false;
} else {
$assorted_heap[$v['invoice_products_id']] = [$k, $v['amount']];
}
return true;
};
$walk_function = function(&$v, $k) {
global $assorted_heap;
$v['amount'] = $assorted_heap[$v['invoice_products_id']][1];
};
$new_arr = array_filter($arr,
$filter_function,
ARRAY_FILTER_USE_BOTH
);
array_walk($new_arr, $walk_function);
unset($assorted_heap);
print_r($new_arr);
Output
Array
(
[0] => Array
(
[id] => 9
[invoice_products_id] => 2
[amount] => 2.9
)
[1] => Array
(
[id] => 10
[invoice_products_id] => 3
[amount] => 3.2
)
)
Here is an array with TWO products. The difference between them is in price and last modification date.
$array = array(
"0" => array
(
"id" => 1,
"name" => apple,
"product_price" => 5,
"date_and_time" => 2017-11-01
),
"1" => array
(
"id" => 1,
"name" => apple,
"product_price" => 6,
"last_mod_date" => 2017-11-02
),
"2" => array
(
"id" => 2,
"name" => orange,
"product_price" => 4,
"last_mod_date" => 2017-11-03
),
"3" => array
(
"id" => 2,
"name" => orange,
"product_price" => 3,
"last_mod_date" => 2017-11-04
));
My question is how to build a new array for each product in array, where the last modification date has a max value? So, I need to compare each product in array in terms of modification date and then push them to new array ( $products = array(); )
So I'd like to receive an array where:
An apple where price is equal to six and date is 2017-11-02, because
the date is greater than date where the price is equal to five,
and orange where the pice is equal to three and the date is
2017-11-04, because the date is greater than date where price is
equal to four
In this case it should look like:
$products = array(
"0" => array
(
"id" => 1,
"name" => apple,
"product_price" => 6,
"last_mod_date" => 2017-11-02
),
"1" => array
(
"id" => 2,
"name" => orange,
"product_price" => 3,
"last_mod_date" => 2017-11-04
));
Many thanks for your support.
Here is an approach that provides very little informational or educational value but leverages PHP native array functions.
<?php
function getLatestById($id, $data) {
foreach ($data as $key => $row) {
$idColumn[$key] = $row['id'];
$modifiedColumn[$key] = $row['modified'];
}
array_multisort($idColumn, SORT_ASC, $modifiedColumn, SORT_DESC, $data);
$k = array_search(1, array_column($data, 'id'));
return $data[$k];
}
$foo = [];
$foo[] = ['id' => 1, 'modified' => '2017-11-01', 'price' => 5];
$foo[] = ['id' => 1, 'modified' => '2017-11-02', 'price' => 6];
$foo[] = ['id' => 2, 'modified' => '2017-11-03', 'price' => 4];
$foo[] = ['id' => 2, 'modified' => '2017-11-04', 'price' => 3];
var_dump(getLatestById($id, $foo));
So the thinking is, sort by id, then sort by modified. Once you've got a sorted array you would just snag the first occurrence by ID.
For more illustrative code I'd probably write a loop, in it populate a new array using ID as the index. Compare existing value against one iterating on, if modified greater (more recent) overwrite. Something like...
$foo = [];
$foo[] = ['id' => 1, 'modified' => '2017-11-01', 'price' => 5];
$foo[] = ['id' => 1, 'modified' => '2017-11-02', 'price' => 6];
$foo[] = ['id' => 2, 'modified' => '2017-11-03', 'price' => 4];
$foo[] = ['id' => 2, 'modified' => '2017-11-04', 'price' => 3];
$a = [];
foreach ($foo as $k => $v) {
if (empty($a[$v['id']]) || $a[$v['id']]['modified'] < $v['modified']) {
$a[$v['id']] = $v;
}
}
var_dump($a);
Or leverage your database and don't do this in code.
I'm stuck with transforming flat array to multidimensional tree like. I have already done it, but I used references, which creates another set of problems down the line, so I need to do this without references.
Input array:
Array
[
1 =>[
'content_id' => 1,
'sort_order' => 1,
'level' => 1
],
2 =>[
'content_id' => 7,
'sort_order' => 2,
'level' => 2
],
3 =>[
'content_id' => 4,
'sort_order' => 3,
'level' => 2
],
4 =>[
'content_id' => 2,
'sort_order' => 4,
'level' => 3
],
5 =>[
'content_id' => 3,
'sort_order' => 5,
'level' => 1
],
6 =>[
'content_id' => 6,
'sort_order' => 6,
'level' => 1
],
7 =>[
'content_id' => 5,
'sort_order' => 7,
'level' => 2
]
]
Output array:
1 => [
'id' = 1,
'visited' = 0,
'children' => [
2 => [
'id' => 7,
'visited' => 0,
'children' => []
],
3 => [
'id' => 4,
'visited' => 0,
'children' => [
4 => [
'id' = 2,
'visited' = 0,
'children' => []
]
]
],
5 => [
'id' => 3,
'visited' => 0,
'children' => []
],
6 => [
'id' => 6,
'visited' => 0,
'children' => [
7 => [
'id' => 5,
'visited' => 0,
'children => []
]
]
]
Any idea how to tackle a problem like this without having direct parent relation set? I can use recursion, but references are problem.
Oooh, this kind of problems do tickle my fancy. So, here is my solution:
<?php
$origArray = array(
array('content_id' => 1, 'sort_order' => 1, 'level' => 1),
array('content_id' => 7, 'sort_order' => 2, 'level' => 2),
array('content_id' => 4, 'sort_order' => 3, 'level' => 2),
array('content_id' => 2, 'sort_order' => 4, 'level' => 3),
array('content_id' => 3, 'sort_order' => 5, 'level' => 1),
array('content_id' => 6, 'sort_order' => 6, 'level' => 1),
array('content_id' => 5, 'sort_order' => 7, 'level' => 2),
);
function sortByOrder($a, $b) {
if ($a['sort_order'] == $b['sort_order']) {
return 0;
}
return ($a['sort_order'] < $b['sort_order']) ? -1 : 1;
}
function createHierarchicalArray($arr) {
$result = array();
foreach ($arr as $el) {
$result = insertArrayElement($result, $el['content_id'], $el['level']);
}
return $result;
}
function insertArrayElement($array, $id, $level, $currentLevel = 1) {
if ($level > $currentLevel) {
$ids = array_keys($array);
$currentId = end($ids);
if (!isset($array[$currentId]['children'])) {
$array[$currentId]['children'] = array();
}
$array[$currentId]['children'] = insertArrayElement($array[$currentId]['children'], $id, $level, $currentLevel + 1);
} else {
$array[$id] = array();
}
return $array;
}
// Could do without this, if the array is already sorted. Otherwise it's a necessary step.
uasort($origArray, 'sortByOrder');
$result = createHierarchicalArray($origArray);
var_dump($result);
Edit: Changed the code to incorporate the changes in the question.
I have the following pairs and they are in the same array:
[
["ID" => 0, "User" => "Test" , "Type" => 3, "Target" => "Caris"],
["ID" => 1, "User" => "Test1", "Type" => 3, "Target" => "Caris"],
["ID" => 2, "User" => "Test2", "Type" => 4, "Target" => "Shirone"],
["ID" => 3, "User" => "Test3", "Type" => 3, "Target" => "Caris"]
]
I want to get the kinds of them, so I using the following code:
$SortList = [];
foreach($Notif as $Key => $Value)
array_push($SortList, ['Type' => $Value['Type'],
'Target' => $Value['Target']]);
and get this:
[
["Type" => 3, "Target" => "Caris"],
["Type" => 3, "Target" => "Caris"],
["Type" => 4, "Target" => "Shirone"],
["Type" => 3, "Target" => "Caris"]
]
But what I really want is something like this:
[
["Type" => 3, "Target" => "Caris"],
["Type" => 4, "Target" => "Shirone"]
]
I want to merge the pairs if they were same value,
(array_merge() seems can only used for non-pair)
How can I merge them like something above?
$SortList = [];
foreach($Notif as $Key => $Value) {
// Just save only value for the same pair, use them concatenated as the key
$SortList[$Value['Type']."_".$Value['Target']] =
array('Type' => $Value['Type'], 'Target' => $Value['Target']);
}
// remove extra stuff (the keys) that was added to prevent duplicates
$SortList = array_values($SortList);