PHP - how to distribute items into two arrays base on values - php

I have this array,
Array
(
[0] => Array
(
[id] => 1
[name] => Item 1
[price] => 10
[weight] => 200
)
[1] => Array
(
[id] => 2
[name] => Item 2
[price] => 100
[weight] => 20
)
[2] => Array
(
[id] => 3
[name] => Item 3
[price] => 30
[weight] => 300
)
[3] => Array
(
[id] => 4
[name] => Item 4
[price] => 20
[weight] => 500
)
[4] => Array
(
[id] => 6
[name] => Item 6
[price] => 40
[weight] => 10
)
[5] => Array
(
[id] => 7
[name] => Item 7
[price] => 200
[weight] => 10
)
)
And I want to split it into two, so I get this result,
Array
(
[0] => Array
(
[0] => Array
(
[id] => 1
[name] => Item 1
[price] => 10
[weight] => 200
)
[1] => Array
(
[id] => 3
[name] => Item 3
[price] => 30
[weight] => 300
)
[2] => Array
(
[id] => 7
[name] => Item 7
[price] => 200
[weight] => 10
)
)
[1] => Array
(
[0] => Array
(
[id] => 4
[name] => Item 4
[price] => 20
[weight] => 500
)
[1] => Array
(
[id] => 6
[name] => Item 6
[price] => 40
[weight] => 10
)
[2] => Array
(
[id] => 2
[name] => Item 2
[price] => 100
[weight] => 20
)
)
)
Any ideas?
The tricky of this is that the total price of each package must not be more than 250. while the total weight of each must be as even as possbile (even thought it is impossible). You can see what I mean in this picture,
name weight price
package 1
Item 1 200 10
Item 3 300 30
Item 7 10 200
(total) 510 240
package 2
Item 4 500 20
Item 6 10 40
Item 2 20 100
(total) 530 160
So is it possible to move around the items between these two packages so that total weights are distributed 'evenly'? It seems that it cannot be achieved without 'moving' them manually. I can't think of any way to achieve the goal by automatic programme. Can you?

Sort the array by weight
usort($array, function($a, $b) {return $a['weight']>$b['weight'];});
We init our result tables, with a price and weight counters
$sum=Array(
Array("weight" => 0, "price" => 0, "res" => Array()),
Array("weight" => 0, "price" => 0, "res" => Array()));
Then we loop on array
while ($obj=array_pop($array)) {
We select the lower result array
$ind=($sum[0]['weight']<$sum[1]['weight']) ? 0 : 1;
except if it has reached the max amount
if ($sum[$ind]['price']+$obj['price']>250) {
$ind=1-$ind;
## object will be skipped if it can't fit in the allowed amount
if ($sum[$ind]['price']+$obj['price']>250) continue;
}
and then we fill it
array_push($sum[$ind]['res'], $obj);
$sum[$ind]['weight']+=$obj['weight'];
$sum[$ind]['price']+=$obj['price'];
}
print_r($sum);
Result as expected:
Array
(
[0] => Array
(
[weight] => 510
[price] => 240
[res] => Array
(
[0] => Array
(
[id] => 3
[name] => Item 3
[price] => 30
[weight] => 300
)
[1] => Array
(
[id] => 1
[name] => Item 1
[price] => 10
[weight] => 200
)
[2] => Array
(
[id] => 7
[name] => Item 7
[price] => 200
[weight] => 10
)
)
)
[1] => Array
(
[weight] => 530
[price] => 160
[res] => Array
(
[0] => Array
(
[id] => 4
[name] => Item 4
[price] => 20
[weight] => 500
)
[1] => Array
(
[id] => 2
[name] => Item 2
[price] => 100
[weight] => 20
)
[2] => Array
(
[id] => 6
[name] => Item 6
[price] => 40
[weight] => 10
)
)
)
)

It have nothing to do with PHP or arrays. As I understand your question it's kind of Multiple knapsack problem. So it's lots of math (see some solution here) and maybe easiest way is to programmatically chaeck all possible variants.

Related

Php creating associative array from another array

I am using an array that I get from a database and I would like to create an associative array from that one.
Here is the code I am using:
print_r($data_sites);
// Format for easy use
$data_sites_formatted = array();
foreach ($data_sites as $key => $row) {
if (empty($data_formatted[$row->project_loe_id])) {
$data_sites_formatted[$row->project_loe_id] = array();
}
$data_sites_formatted[$row->project_loe_id][$row->name] = array();
$data_sites_formatted[$row->project_loe_id][$row->name]['id'] = $row->id;
$data_sites_formatted[$row->project_loe_id][$row->name]['quantity'] = $row->quantity;
$data_sites_formatted[$row->project_loe_id][$row->name]['loe_per_quantity'] = $row->loe_per_quantity;
}
print_r($data_sites_formatted);
Here is the information I receive from the database:
Illuminate\Support\CollectionObject ( [items:protected] => Array (
[0] => stdClass Object ( [id] => 1 [project_loe_id] => 1 [name] => site [quantity] => 20 [loe_per_quantity] => 1 )
[1] => stdClass Object ( [id] => 2 [project_loe_id] => 1 [name] => switches [quantity] => 5 [loe_per_quantity] => 3 )
[2] => stdClass Object ( [id] => 3 [project_loe_id] => 2 [name] => site [quantity] => 20 [loe_per_quantity] => 1 )
[3] => stdClass Object ( [id] => 4 [project_loe_id] => 2 [name] => ap [quantity] => 5 [loe_per_quantity] => 3 )
[4] => stdClass Object ( [id] => 5 [project_loe_id] => 2 [name] => wireless [quantity] => 5 [loe_per_quantity] => 3 ) ) )
And when I do the transformation, here is the result:
Array (
[1] => Array ( [switches] => Array ( [id] => 2 [quantity] => 5 [loe_per_quantity] => 3 ) )
[2] => Array ( [wireless] => Array ( [id] => 5 [quantity] => 5 [loe_per_quantity] => 3 ) ) )
I lost 3 lines and I really have no idea why. I can see when I look into details step by step that it deletes some lines from 1 iteration to the next:
Iteration:0
Array (
[1] => Array ( [site] => Array ( [id] => 1 [quantity] => 20 [loe_per_quantity] => 1 ) ) )
Iteration: 1
Array (
[1] => Array ( [switches] => Array ( [id] => 2 [quantity] => 5 [loe_per_quantity] => 3 ) ) )
Iteration: 2
Array (
[1] => Array ( [switches] => Array ( [id] => 2 [quantity] => 5 [loe_per_quantity] => 3 ) )
[2] => Array ( [site] => Array ( [id] => 3 [quantity] => 20 [loe_per_quantity] => 1 ) ) )
Iteration: 3
Array (
[1] => Array ( [switches] => Array ( [id] => 2 [quantity] => 5 [loe_per_quantity] => 3 ) )
[2] => Array ( [ap] => Array ( [id] => 4 [quantity] => 5 [loe_per_quantity] => 3 ) ) )
Iteration: 4
Array (
[1] => Array ( [switches] => Array ( [id] => 2 [quantity] => 5 [loe_per_quantity] => 3 ) )
[2] => Array ( [wireless] => Array ( [id] => 5 [quantity] => 5 [loe_per_quantity] => 3 ) ) )
You can see from iteration 0 to iteration 1, it deleted the line from iteration 0 and in iteration 1 I should have 2 lines.
You have a typo here:
if (empty($data_formatted[$row->project_loe_id])) {
$data_sites_formatted[$row->project_loe_id] = array();
}
$data_formatted is never defined (you meant to write $data_sites_formatted) so empty($data_formatted[$row->project_loe_id]) is always true, and always runs the next line, replacing anything previously added to $data_sites_formatted[$row->project_loe_id] with an empty array. So all you end up with is the last item to be added in each group.

sum of array based on key(Group by user)

enter image description here
This is my first array which i get from mysql
Array
([0] => Array
(
[created_by] => 4
[count] => 1
[total] => 300
)
[1] => Array
(
[created_by] => 4
[count] => 1
[total] => 450
)
[2] => Array
(
[created_by] => 3
[count] => 1
[total] => 500
)
)
I need a output as
[0] => Array
(
[created_by] => 4
[count] => 2
[total] => 750
)
[1] => Array
(
[created_by] => 3
[count] => 1
[total] => 500
)
Sum of array total based on created_by
Need to group by created_by count.

Create a new array using another array in PHP

I have array of categories like this and I want to merge the same value like 1 and 0 index value etc in another new array how it is possible.
Array
(
[0] => Array
(
[id] => 29
[parentId] => 0
[serviceName] => Hair
[parentServiceImg] => 7ffb7f5aa2a210ba927e9de64ef17f93.jpeg
[subCategory] => Array
(
[id] => 30
[parentId] => 29
[serviceName] => Blow Out
[subCategory] => Array
(
[id] => 31
[parentId] => 30
[serviceName] => Add Clients Hair Extensions & Style
[subCategory] => Array
(
[id] => 49
[parentId] => 31
[serviceName] => Hair style color
[servicePrice] => 100
)
)
)
)
[1] => Array
(
[id] => 1
[parentId] => 0
[serviceName] => Makeup
[parentServiceImg] => e00d3576847fef9f717d1de2647ed954.jpeg
[subCategory] => Array
(
[id] => 2
[parentId] => 1
[serviceName] => Special Event Makeup
[subCategory] => Array
(
[id] => 3
[parentId] => 2
[serviceName] => Add Airbrush
[servicePrice] => 232
)
)
)
[2] => Array
(
[id] => 1
[parentId] => 0
[serviceName] => Makeup
[parentServiceImg] => e00d3576847fef9f717d1de2647ed954.jpeg
[subCategory] => Array
(
[id] => 6
[parentId] => 1
[serviceName] => Photoshot Makeup
[subCategory] => Array
(
[id] => 7
[parentId] => 6
[serviceName] => Add Airbrush
[servicePrice] => 8
)
)
)
[3] => Array
(
[id] => 1
[parentId] => 0
[serviceName] => Makeup
[parentServiceImg] => e00d3576847fef9f717d1de2647ed954.jpeg
[subCategory] => Array
(
[id] => 2
[parentId] => 1
[serviceName] => Special Event Makeup
[subCategory] => Array
(
[id] => 4
[parentId] => 2
[serviceName] => Add Lashes
[servicePrice] => 6
)
)
)
[4] => Array
(
[id] => 29
[parentId] => 0
[serviceName] => Hair
[parentServiceImg] => 7ffb7f5aa2a210ba927e9de64ef17f93.jpeg
[subCategory] => Array
(
[id] => 2
[parentId] => 1
[serviceName] => Special Event Makeup
[subCategory] => Array
(
[id] => 47
[parentId] => 29
[serviceName] => Wedding Day Mother of the Bride / Mother of the Groom Hair Touch Ups
[servicePrice] => 5
)
)
)
)
I want to 0 index value merge with 4 index value and get on 0 index of new array and 1 to 3 index value merge and get on 1 index in new array using php. I need help for this. thanks.
It should help you:
<?php
$your_array = [0=>['array1'], 1=>['array2'],2=>['array3'], 3=>['array4'], 4=>['array5']];
$new_array = [];
$first = array_shift($your_array);
$last = array_pop($your_array);
$array = array_merge($first, $last);
$new_array[] = $array;
$new_array[] = $your_array;
?>

How to remove duplicate data in an array?

I have the following array:
Array
(
[0] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 1
[category_id] => 1
[amount] => 50
[cost] => 8320
[paid] => 0
[comment] => transportation and others cost: 100
[created] => 2015-06-22 12:09:20
)
[0] => Array
(
[total_sell] => 6
)
)
[1] => Array
(
[Import] => Array
(
[product_id] => 2
[id] => 2
[category_id] => 2
[amount] => 15
[cost] => 3000
[paid] => 0
[comment] =>
[created] => 2015-06-22 12:10:36
)
[0] => Array
(
[total_sell] => 1
)
)
[2] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 3
[category_id] => 1
[amount] => 15
[cost] => 2000
[paid] => 0
[comment] =>
[created] => 2015-06-22 12:10:58
)
[0] => Array
(
[total_sell] => 6
)
)
[3] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 4
[category_id] => 1
[amount] => 50
[cost] => 8000
[paid] => 0
[comment] =>
[created] => 2015-06-23 01:10:10
)
[0] => Array
(
[total_sell] => 6
)
)
)
I want to remove duplicate entry of [Import][product_id]. So my expected result is :
Array
(
[0] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 1
[category_id] => 1
[amount] => 50
[cost] => 8320
[paid] => 0
[comment] => transportation and others cost: 100
[created] => 2015-06-22 12:09:20
)
[0] => Array
(
[total_sell] => 6
)
)
[1] => Array
(
[Import] => Array
(
[product_id] => 2
[id] => 2
[category_id] => 2
[amount] => 15
[cost] => 3000
[paid] => 0
[comment] =>
[created] => 2015-06-22 12:10:36
)
[0] => Array
(
[total_sell] => 1
)
)
)
Would you write a function to filter this type of array and produce expected result. I have been googling for 2 days but no luck.
This is a handy one liner that should do the trick:
$unique= array_map("unserialize", array_unique(array_map("serialize", $original)));
If the underlying arrays are not identical, that won't work, in which case I think you could do:
$unique = array_intersect_key($original ,
array_unique(
array_map(function($item) {
return $item['Import']['product_id'];
}, $original)
)
);
Tested: http://sandbox.onlinephpfunctions.com/code/8aee5cbd614e0ddd1a03dfaa7e98c72fbbe7d68d
Here is a quick stable sort and reduce which runs in linearithmic time. First-encountered product Id's are kept, and entries with duplicate product Id's are ignored.
// Stable sort
sort($in);
// Reduce
$out = array_reduce($in, function(&$acc, &$item){
if($item['Import']['product_id'] !== #$acc[sizeof($acc)-1]['Import']['product_id']) {
$acc[] = $item;
}
return $acc;
}, []);
Demo: http://ideone.com/BP0eUJ
Update: Here is an even better linear-time algorithm that does the same as above using a fast "hash table" lookup. Again, the first-encountered product Id is kept and subsequent ones of the same Id are ignored.
$out = [];
$hashTable = [];
foreach($in as $item) {
$pid = $item['Import']['product_id'];
if(!isset($hashTable[$pid])) {
$out[] = $item;
$hashTable[$pid] = true;
}
}
Demo: http://ideone.com/5RF0og

PHP add arrays to an array on a specific element

I am trying to merge 2 arrays a single array on a multidimensional array where a given key-value = a value
the first array looks like this:
Array
(
[0] => Array
(
[id] => 4
[subcategories] => Array
(
[0] => Array
(
[id] => 5
[category_order] => 0
[parent_id] => 4
[name] => Audio Equipment
)
[1] => Array
(
[id] => 6
[category_order] => 0
[parent_id] => 4
[name] => Home Entertainment
)
[2] => Array
(
[id] => 7
[category_order] => 0
[parent_id] => 4
[name] => Photography
)
[3] => Array
(
[id] => 8
[category_order] => 0
[parent_id] => 4
[name] => Portable Audio
)
[4] => Array
(
[id] => 9
[category_order] => 0
[parent_id] => 4
[name] => Televisions
)
)
)
)
and the second like this:
Array
(
[0] => Array
(
[id] => 10
[parent_id] => 5
[name] => Amplifiers & Receivers
)
[1] => Array
(
[id] => 11
[parent_id] => 5
[name] => Audio Systems
)
[2] => Array
(
[id] => 12
[parent_id] => 5
[name] => Cassette Decks
)
[3] => Array
(
[id] => 13
[parent_id] => 5
[name] => CD Players
)
[4] => Array
(
[id] => 14
[parent_id] => 5
[name] => Radios
)
[5] => Array
(
[id] => 15
[parent_id] => 5
[name] => HiFi Speakers
)
)
What I want to do is add each of the second arrays to a sub array of the first multidimensional array where the parent_id of the second array = the id of the subcategories array of the first array so it will look like this:
array
(
[0]=> Array
(
[id] => 4
[subcategories] => Array
(
[0] => Array
(
[id] => 5
[category_order] => 0
[parent_id] => 4
[name] => Audio Equipment
[subsubcategories] = array
(
[id] => 10
[parent_id] => 5
[name] => Amplifiers & Receivers
)
)
Something like this should work just rename the array names because you didn't provide them. But I think you'll get the idea :) Mainly you loop through all subcategories with foreach loop or another you'll get the parent id and can access the main array with that parent id and save the sub categories info in there.
foreach( $sub_array as $item ) {
$main_array[ category_id ][ $item[ 'parent_id' ] ][ 'subsubcategories' ] = $item;
}

Categories