php make new array from old array - php

I have some cases where I need to do a split item for my shipment from items order.
the rule is max weight per 1 shipment is 5.
this is my items order :
$items = [
[
"sku" => "SKU-A",
"name" => "Product A",
"weight" => 7,
"dimension" => "20x30x10"
],
[
"sku" => "SKU-B",
"name" => "Product B",
"weight" => 4,
"dimension" => "10x10x20"
],
];
after doing split, i expect the result to this:
// will create new array
// limit weight per shipment max 5kg
$item1 = [
[
"sku" => "SKU-A",
"name" => "Product A",
"weight" => 5,
"dimension" => "20x30x10"
]
];
$item2 = [
[
"sku" => "SKU-A",
"name" => "Product A",
"weight" => 2,
"dimension" => "20x30x10"
], // this item from SKU-A where w => 7 - 5 = 2
[
"sku" => "SKU-B",
"name" => "Product B",
"weight" => 3,
"dimension" => "10x10x20"
],
];
$item3 = [
[
"sku" => "SKU-B",
"name" => "Product B",
"weight" => 1,
"dimension" => "10x10x20"
],// this item from SKU-B where w => 7 - 5 = 2
];
what's the posible way to do that? thank you.

#catLovers, I have made this code as desired... Please improvise/ optimise as necessary.
$items = [
[
"sku" => "SKU-A",
"name" => "Product A",
"weight" => 7,
"dimension" => "20x30x10"
],
[
"sku" => "SKU-B",
"name" => "Product B",
"weight" => 4,
"dimension" => "10x10x20"
],
];
$newItems = array();
for ($x = 0; $x <= count($items)-1; $x++) {
if ($items[$x]['weight'] > 5) {
$weight = $items[$x]['weight'];
$wt =5;
do {
$temp = array([
'sku' => $items[$x]['sku'],
'name' => $items[$x]['name'],
'weight' => $wt,
'dimension' => $items[$x]['dimension']
]);
array_push($newItems,$temp);
$weight=$weight-5;
if ($weight <=5){ $wt=$weight;}
} while ($weight <= 5);
echo "<pre>";
print_r($temp);
echo "</pre>";
}
else {
array_push($newItems,$items[$x]);
}
}
echo "<pre>";
print_r($newItems);
echo "</pre>";

Related

Php Recursivity: Convert a multidimensional associative array into an array that contains each level of data

I am looking for the best way to convert a multidimensional associative array into a new array, where each row is the concatenation of each column ex :
$datas[] = [
"id" => "1000",
"parent" => "0",
"level" => "1",
"children" => [
[
"id" => "1001",
"parent" => "1000",
"level" => "2",
"children" => [
[
"id" => "1002",
"parent" => "1001",
"level" => "3",
"children" => [
[
"id" => "1003",
"parent" => "1002",
"niveau" => "4",
],
[
"id" => "1004",
"parent" => "1002",
"niveau" => "4",
],
[
"id" => "1005",
"parent" => "1002",
"niveau" => "4",
]
]
],
[
]
]
],
[
"id" => "1006",
"parent" => "1000",
"level" => "2"
]
],
[
"id" => "1007",
"parent" => "0",
"level" => "1"
]
];
Here's my method :
public function recursData(array $datas, &$str ="", &$row =[], int $level = 0)
{
$level++;
foreach ($datas as $data) {
foreach($data as $key => $d) {
if (is_array($d)) {
$this->recursData($d, $str, $row,$level);
} else {
$str.= "{$level}_{$key}_{$d}|";
if ($key == "parent") {
$row[] = $str;
}
}
}
}
return $row;
}
Output (not what i'm looking for) :
array:8 [
0 => "1_id_1000|1_parent_0|"
1 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|"
2 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|"
3 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|"
4 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|"
5 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|4_id_1005|4_parent_1002|"
6 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|4_id_1005|4_parent_1002|2_id_1006|2_parent_1000|"
7 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|4_id_1005|4_parent_1002|2_id_1006|2_parent_1000|1_id_1007|1_parent_0|"
]
The output i'm looking for:
array:8 [
0 => "1_id_1000|1_parent_0"
1 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000"
2 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001"
3 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|3_parent_1002"
4 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1004|3_parent_1002"
5 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1005|3_parent_1002"
6 => "1_id_1000|1_parent_0|2_id_1006|2_parent_1000"
7 => "1_id_1007|1_parent_0"
]
I'm stuck to finish this properly, I tried lot of things, but can't understand what to do obtain what I want to resolve this. Hope someone could help :)

Merging the two array of arrays based on a field value

There are two arrays of arrays. $user and $experience are two arrays and i want to achieve $final as my expected output.
I have two arrays:
$user = [
[
"country" => "aus",
"new_experiences" => 0,
"new_users" => 6
],
[
"country" => "jpn",
"new_experiences" => 0,
"new_users" => 5
]
];
$experience = [
[
"country" => "jpn",
"new_experiences" => 12,
"new_users" => 0
],
[
"country" => "usa",
"new_experiences" => 10,
"new_users" => 0
]
];
After merging these two arrays based on country, how can i get:
$final = [
[
"country" => "aus",
"new_experiences" => 0,
"new_users" => 6
],
[
"country" => "jpn",
"new_experiences" => 12,
"new_users" => 5
],
[
"country" => "usa",
"new_experiences" => 10,
"new_users" => 0
]
];
Try this
array_unique(array_merge($array1,$array2), SORT_REGULAR);
http://se2.php.net/manual/en/function.array-unique.php
You can achieve your GOal using this simple steps:
Iterate and arrange your array into a single array using foreach
Create a key-value array, just like I have created $issetArray
Push all the value in a $final array, you will get the desired output
I have created a simple logic using foreach loop, isset() and array_push()
$user = array(
array(
"country" => "aus",
"new_experiences" => 0,
"new_users" => 6
),
array(
"country" => "jpn",
"new_experiences" => 0,
"new_users" => 5
)
);
$experience = array(
array(
"country" => "jpn",
"new_experiences" => 12,
"new_users" => 0
),
array(
"country" => "usa",
"new_experiences" => 10,
"new_users" => 0
)
);
$final = array();
$issetArray = array();
foreach($user as $key => $value)
{
if(isset($issetArray[$value['country']]))
{
$issetArray[$value['country']]['new_experiences'] = $value;
$issetArray[$value['country']]['new_users'] = $value;
}
else
{
$issetArray[$value['country']] = $value;
}
}
foreach($experience as $key => $value)
{
if(isset($issetArray[$value['country']]))
{
$issetArray[$value['country']]['new_experiences'] = $value['new_experiences'];
$issetArray[$value['country']]['new_users'] = $value['new_users'];
}
else
{
$issetArray[$value['country']] = $value;
}
}
foreach($issetArray as $value)
{
array_push($final, $value);
}
echo "<pre>";
print_r($final);
Click on the link to know more about isset() and array_push()

Foreach Array error (PHP)

I want to create dynamic menu with looping an array be 1 object menu. But error occured.
Our code is below it:
$menus = [{"id" => 1, "label" => "content", "parent_id" => 0},{"id" => 2, "label" => "inbox", "id" => 3, "parent_id" => 0}, {"id" => 4, "label" => "item", "parent_id" => 0}];
$sub_menus = [{"id" => 5, "label" => "banner", "parent_id" => 1},{"id" => 6, "label" => "ads", "parent_id" => 1}];
foreach($menus as $row => $value){
$nav[$row] = $value;
foreach($sub_menus as $r => $v) {
if($v['parent_id'] == $value['id']){
$nav[$row]['sub_menu'][$r] = $v;
}
}
}
I get error notif, "Indirect modification of overloaded element of App\Menu has no effect"
Please Help me :)
The code is working. You have a lot of bugs in your arrays.
Fixed:
$menus = [
[
"id" => 1,
"label" => "content",
"parent_id" => 0
],
[
"id" => 2,
"label" => "inbox",
"parent_id" => 0
],
[
"id" => 4,
"label" => "item",
"parent_id" => 0
]
];
$sub_menus = [
[
"id" => 5,
"label" => "banner",
"parent_id" => 1
],
[
"id" => 6,
"label" => "ads",
"parent_id" => 1
]
];
foreach($menus as $row => $value){
$nav[$row] = $value;
foreach($sub_menus as $r => $v) {
if($v['parent_id'] == $value['id']){
$nav[$row]['sub_menu'][$r] = $v;
}
}
}
You have a broken array, something like an incorrect conversion of json to an array;
You can test(execute) it here (working example)

Sort documents based on array field size

I'm trying to use the size of an array called "empofthemonth" to sort each field returned by their amount of employee of the month wins.
Here is the insert code:
$db->users->insert(
["firstname" => "firstname1",
"lastname" => "test",
"email" => "test#email.org.uk",
"keyinfo" =>
["age" => 22,
"gender" => "Male",
"yearsemployed" => 1,
"empofthemonth" => ["Apr"]]
]);
$db->users->insert(
["firstname" => "firstname2",
"lastname" => "test2",
"email" => "test#email.co.uk",
"keyinfo" =>
["age" => 24,
"gender" => "Female",
"yearsemployed" => 5,
"empofthemonth" => ["Feb", "Mar"]]
]);
$db->users->insert(
["firstname" => "firstname3",
"lastname" => "test2",
"email" => "test#email.com",
"keyinfo" =>
["age" => 31,
"gender" => "Female",
"yearsemployed" => 2,
"empofthemonth" => ["Jan", "May", "Jun"]]
]);
I realise that aggregation might be used but i cannot work out the full syntax.
To conclude the query results should be in this order:
firstname3 (3 emp of the months)
firstname2 (2)
firstname1 (1)
We need to $project our documents and return the $size then $sort each document by that "size" in descending order. Note that to access the array field, we need to use the "dot notation".
db.users.aggregate(
[
{ "$project": {
"firstname": 1,
"lastname": 1,
"email": 1,
"keyinfo": 1,
"sz": { "$size": "$keyinfo.empofthemonth" }
}},
{ "$sort": { "sz": -1 } }
]
)
Everything in PHP:
$db->users->aggregate(
[
[ "$project" => [
"firstname" => 1,
"lastname" => 1,
"email" => 1,
"keyinfo" => 1,
"sz" => [ "$size" => "$keyinfo.empofthemonth" ]
]],
[ "$sort" => [ "sz" => -1 ] ]
]
)

Populate multidimensional array's rank column with dense rank number

My array structure is as follows -
[
[
"points" => 10,
"details" => ["name" => "Team A", "rank" => ""]
],
[
"points" => 10,
"details" => ["name" => "Team B", "rank" => ""]
],
[
"points" => 8,
"details" => ["name" => "Team C", "rank" => ""]
],
[
"points" => 6,
"details" => ["name" => "Team D", "rank" => ""]
],
]
Now I want populate the array's "rank" value with the appropriate dense rank. Expected result:
[
[
"points" => 10,
"details" => ["name" => "Team A", "rank" => 1]
],
[
"points" => 10,
"details" => ["name" => "Team B", "rank" => 1]
],
[
"points" => 8,
"details" => ["name" => "Team C", "rank" => 2]
],
[
"points" => 6,
"details" => ["name" => "Team D", "rank" => 3]
],
]
How can I achieve this output? I tried looping through each element in the array and comparing points, but I didn't find that to be really efficient.
How about to create another array and store desired result there
$array = array(
array(
"points" => 10,
"details" => array(
"name" => "Team A",
"rank" => ""
)
),
array(
"points" => 11,
"details" => array(
"name" => "Team B",
"rank" => ""
)
)
);
$c = 0; // count identifier
$n = array(); // create new array
for ($i=0;$i<count($array);$i++){ // loop through each array
foreach ($array[$i] as $value){ // loop through into sub arrays
if (is_array($value)){
$n[$i]['details'] = array(
"name" => $value['name'],
"rank" => $c
);
$c++;
} else {
$n[$i]['points'] = $value;
}
}
}
print_r($n);
Output will be:
Array ( [0] => Array ( [points] => 10 [details] => Array ( [name] => Team A [rank] => 0 ) ) [1] => Array ( [points] => 11 [details] => Array ( [name] => Team B [rank] => 1 ) ) )
A bit bruteforce but it should work.
$array = array(
array(
"points" => 10,
"details" => array(
"name" => "Team A",
"rank" => ""
)
),
array(
"points" => 11,
"details" => array(
"name" => "Team B",
"rank" => ""
)
),
array(
"points" => 10,
"details" => array(
"name" => "Team A",
"rank" => ""
)
),
array(
"points" => 11,
"details" => array(
"name" => "Team B",
"rank" => ""
)
)
);
$points = array();
foreach($array as $key => $arr){
$points[] = $arr['points'];
}
asort($points);
foreach($points as $pkey => $point){
foreach($array as $akey => $arr){
if($point == $arr['points']){
$array[$akey]['details']['rank'] = $pkey+1;
}
}
}
var_dump($array);
Since your multidimensional input array is already sorted descending by the points column, you can loop through the array and modify its rank data by reference while conditionally incrementing the rank variable.
Code: (Demo)
$denseRank = 0;
foreach ($array as ['points'=> $points, 'details' => ['rank' => &$rank]]) {
$denseRanks[$points] ??= ++$denseRank;
$rank = $denseRanks[$points];
}
var_export($array);
The above snippet uses "array destructuring" in the foreach() to declare only used variables; it is just as viable to declare &$row and then access its elements in the loop's body.

Categories