create a grouped array from another array - php

I have a big array (read from a file)
$data = array(
array(134, 'Field_A_134', 'Field_B_134'),
array(134, 'Field_C_134', 'Field_D_134'),
array(134, 'Field_E_134', 'Field_F_134'),
array(180, 'Field_A_180', 'Field_B_180'),
array(70, 'Field_A_70', 'Field_B_70'),
array(180, 'Field_C_180', 'Field_D_180'),
...
);
and i want to group into another array by the first key from the first array (ex: 134, 180, 70, ...). Those keys are repeating, but the fields are different.
The array i want to make is:
array(
'134' => array(array(134, 'Field_A_134', 'Field_B_134'), array(134, 'Field_C_134', 'Field_D_134'), array(134, 'Field_E_134', 'Field_F_134')),
'180' => array(array(180, 'Field_A_180', 'Field_B_180'), array(180, 'Field_C_180', 'Field_D_180')),
'70' => array(array(70, 'Field_A_180', 'Field_B_180'))
);
Each key contains an array of arrays that contain the first key.
I was trying to make this:
$f = array();
$pr = array();
foreach($data as $p){
if(isset($f[$p[0]])){
array_push($f[$p[0]], $p);
} else {
$f[$p[0]] = $p;
}
array_push($pr, $f);
}
but it`s not what i want.

The error is in the else part. You need to assign an array, like this:
$f[$p[0]] = [$p];
Or like this, since PHP will create the array on the fly:
$f[$p[0]][] = $p;
And since that code can also be used when the array already exists, you can simplify to this loop:
foreach($data as $p) {
$f[$p[0]][] = $p;
}

Related

How to pass data from a master array to multiple arrays in PHP

I have an array with subarrays, each subarray has 'type' (int) and a 'datetime'. I need to loop trought the array and create new arrays (or objects) with groups of these subarrays in a special way: every 'type' could be [0-3] 0 means startdate and 3 means enddate (1 and 2 are in between for other purposes). Every new array with these subarrays should start with 0 and end with 3.
Im not using any framework, only PHP5 and jQuery. The master array comes from a loop I made from a SQL query with GROUP_CONCAT. I just passed the concat fields to a master array but I need to regroup the subarrays to create some type of registries.
Here is the array I got with subarrays. They are already sorted by datetime, every type '0' means "start date / start new registry" and '3' means "end date / end registry".
$array = [
["tipo"=>0,"fechahora"=>"2019-05-26 09:35:30"],
["tipo"=>1,"fechahora"=>"2019-05-26 10:30:15"],
["tipo"=>2,"fechahora"=>"2019-05-26 10:43:12"],
["tipo"=>3,"fechahora"=>"2019-05-26 14:30:26"],
["tipo"=>0,"fechahora"=>"2019-05-26 15:35:22"],
["tipo"=>3,"fechahora"=>"2019-05-26 16:35:31"],
["tipo"=>0,"fechahora"=>"2019-05-27 08:31:57"],
["tipo"=>1,"fechahora"=>"2019-05-27 10:27:22"],
["tipo"=>2,"fechahora"=>"2019-05-27 10:38:31"],
["tipo"=>3,"fechahora"=>"2019-05-27 14:20:38"],
["tipo"=>0,"fechahora"=>"2019-05-28 09:39:42"],
["tipo"=>1,"fechahora"=>"2019-05-28 11:43:08"],
["tipo"=>2,"fechahora"=>"2019-05-28 11:53:19"],
["tipo"=>3,"fechahora"=>"2019-05-28 14:43:31"],
["tipo"=>0,"fechahora"=>"2019-05-29 10:30:22"],
["tipo"=>3,"fechahora"=>"2019-05-29 14:38:46"]
];
I need to create a new array with subarrays or objects by registry, a registry is an element who have startdate (type 0), somedates in between (type 1,2) and a enddate (type 3). Its important The next subarray have the startdate more current than the older subarray enddate. Every "tipo"+"fechahora" array have more fields (signature, address, etc) so I need to keep these as subarrays:
$newarray = [
'registry0' => [
"startdate"=> ["tipo"=>0,"fechahora"=>"2019-05-26 09:35:30"],
"pauses"=> [
["tipo"=>1,"fechahora"=>"2019-05-26 10:30:15"],
["tipo"=>2,"fechahora"=>"2019-05-26 10:43:12"]
],
"enddate" => ["tipo"=>3,"fechahora"=>"2019-05-26 14:30:26"]
],
'registry1' => [
"startdate"=> ["tipo"=>0,"fechahora"=>"2019-05-26 15:35:22"],
"pauses"=> [],
"enddate" => ["tipo"=>3,"fechahora"=>"2019-05-26 16:35:31"]
],
'registry2' => [
"startdate"=> ["tipo"=>0,"fechahora"=>"2019-05-27 08:31:57"],
"pauses"=> [
["tipo"=>1,"fechahora"=>"2019-05-27 10:27:22"],
["tipo"=>2,"fechahora"=>"2019-05-27 10:38:31"]
],
"enddate" => ["tipo"=>3,"fechahora"=>"2019-05-27 14:20:38"]
]
];
I could use arrays or objects, I dont know hot to develop a loop to regroup arrays like this (starting at one field value and ending with another and so on). I dont even know if there is a simpler way. Any help would be appreciated.
If this could help: I need the registries this way to put into an HTML table, each registry in a row.
EDIT:
Iknow I have to use a loop but I dont know how to "get first element with type 0, create an array, include element, include all other element until type 3, close array, create new array and so on..."
In some code:
$newarray = [];
foreach($array as $element) {
if ($element["tipo"]==0) {
//new subarray
//include this in subarray
}
// include all "tipos" 1,2 in subarray
if ($element["tipo"]==3) {
//include this in subarray
//finish subarray
}
//incude subarray in $newarray
}
return $newarray;
I dont know how to continue.
For this case a simple foreach followed by switch case will do,
$result = [];
$i = 0;
$var = 3; // you can manage this at your will
foreach ($array as $key => $value) {
switch ($value['tipo']) { // passing tipo value here
case 0:
// it will capture for same record for current value of $i
$result['registry' . $i]['startdate'] = $value;
break;
case $var:
// detects last entry and will increment
$result['registry' . $i++]['enddate'] = $value;
break;
default:
// if not 0 and $var then push it in pauses
$result['registry' . $i]['pauses'][] = $value;
break;
}
}
Demo Link.
It is just a case of looping over each of the original array values and creating an entry in a temporary array ($temp in this case) with any values according to type. Then when a type 3 is found, adding this to the $newarray...
$newarray = [];
$temp = [];
$count = 0;
foreach ( $array as $entry ) {
if ( $entry['tipo'] == 0 ) {
$temp = [ 'startdate' => $entry ];
}
else if ( $entry['tipo'] == 3 ) {
$temp["enddate"] = $entry;
$newarray["registry".$count++] = $temp;
}
else {
$temp["pauses"][] = $entry;
}
}

Array Combine in PHP

I am trying to combine keys and values in arrays. I have an product_id with different price.
Let say
Product id and price
id 101 and price is 100
id 105 and price is 200
id 101 and price is 300
list of product ids in array with $product_ids[] and list of price also $price_amount[]
So I preferred to combine the two arrays using array_combine
I made array_combine($product_ids,$price_amount);
Now it appears look like this way
array(2) { [101]=> float(100) [105]=> float(300) }
Is there is a way to add the key elements to the id as something like
array(2) {
[101] => float(400) (100+300)
[105] => float(300)
}
Here is the idea i tried
$products = array();
$order_totalss = array();
foreach (get_posts('post_type=shop_order&numberposts=-1&post_status=publish') as $order) {
$order = new WC_Order($order->ID);
if (wc_customer_bought_product($order->billing_email, $order->user_id, $product_id)) {
$productcounts[] = $product_id;
$order_totalss[] = $order->get_total();
}
}
$arraymergeme = array_combine($productcounts, $order_totalss);
You will have to do this manually I'm afraid:
$total = array();
foreach ($product_ids as $key => $value) {
// each value of product_ids becomes the key
if (isset($total[$value])) {
// we have seen this key before
$total[$value] += $price_amount[$key];
} else {
// new key
$total[$value] = $price_amount[$key];
}
}
Simple code so you can see what's happening clearly:
$ids = array(101, 105, 101);
$prices = array(100, 200, 300);
$totals = array();
foreach ($ids as $key => $id)
{
// Make sure index is defined
if ( ! isset($totals[$id]))
{
// Make sure we have a value
$totals[$id] = 0;
}
// Assuming index $key matches... add to the total
$totals[$id] += $prices[$key];
}
PHP arrays are associative so you can write something like: price['101'] = 100 thereby using the product id as the array index.
Thinking you are looking for something like this. I haven't done php in awhile, so the syntax may need tweaking, but I think the logic is correct.
$cart = array(
"101" => 100,
"105" => 200,
"101" => 300
);
$product_id_arr = array();
foreach ($cart as $product_id => $price) {
if(array_key_exists($product_id, $product_id_arr)){
$product_id_arr[$product_id] = $product_id_arr[$product_id] + $price;
}else{
$product_id_arr[$product_id] = $price;
}
}
array_combine will not do the trick for you. You will have to iterate through the array and total them as you go. Here's an example:
<?php
$product_ids = array('101', '105', '101');
$price_amount = array(100, 200, 300);
$combined = array();
$productCount = count($product_ids);
for($i = 0; $i < $productCount; $i++) {
// if this product_id is not in the $combined array, add its price
// as associative array ('101'=>100)
// but if it is found in $combined, add to its current price
if (!array_key_exists($product_ids[$i], $combined)) {
$combined[$product_ids[$i]] = $price_amount[$i];
} else {
$combined[$product_ids[$i]] += $price_amount[$i];
}
}
print_r($combined);
?>
Results:
Array
(
[101] => 400
[105] => 200
)
Try this
$final_arr = array();
for($i=0;$i<count($product_ids);$i++) {
if(!isset($final_arr[$product_ids[$i]])) {
$final_arr[$product_ids[$i]] = 0;
}
$final_arr[$product_ids[$i]] += $price_amount[$i];
}
Yes you can add key elements to id, basically an array can be created by using the array() language construct. It takes any number of comma-separated key => value pairs as arguments.
array(
key => value,
key2 => value2,
key3 => value3,
...
)
the one you are looking for is associative array. you can definitely specify the key you want and store the value you want at that key.
here is a link that would be helpful

Array search to return similar array key

I am not sure what should be title of this question, If you have better option, don't hesitate to change.
I need to search in an array with team's full name and return the short name. Now I have the following creteria:
$teams = array('MMB' => 'Mumbai', 'MMB' => 'Mumbai Indians');
$Vteam = (array_search($vteam, $teams, true) !== false) ? array_search($vteam, $teams) : substr($vteam, 0, 3);
When I search for 'Mumbai Indians', it returns 'MMB', but when I search for 'Mumbai' alone it returns 'Mum'.
I have around 50 team names in $team array.
How should I code so that on 'Mumbai' and 'Mumbai Indians' search it returns me 'MMB' always?
Any help would be really appreciated.
If you're creating the $teams array by yourself, then form it properly with an array for the values!
$teams = array('MMB' => array( 'Mumbai', 'Mumbai Indians'));
However, if you want a lookup of the short name, invert this design:
$teams = array( 'Mumbai' => 'MMB', 'Mumbai Indians' => 'MMB');
Now, if you want to know Mumbai's short name, just index the array on their name:
echo $teams['Mumbai']; // Output: MMB
echo $teams['Mumbai Indians']; // Output: MMB
If you are doing partial match you will probably need to use a foreach loop:
$search = 'Mumbai';
$team = '';
foreach($teams as $shortname => $longname) {
if(strpos($longname,$search) !== false) {
$team = $shortname;
break;
}
}

find id of post with highest value

I have an array of posts that I want to sort - but before I do, I want to find the id of the post with the highest number of likes.
I loop through the array using a foreach. Although it seems like a waste to do two foreach loops for this - I don't know if there's an alternative when trying to find the highest value beforehand?
Array
(
[0] => Array
(
[id] => 162
[like_count] => 2
etc.
)
[1] => Array
(
[id] => 165
[like_count] => 23
etc.
)
)
So the second post has the highest amount of likes, so I need the ID of 165 - then when I loop through I can do something like
foreach ($posts as $post){
if($most_liked_id == $post["id"]){
// this post is the most liked!
}
}
Any help would be much appreciated - thanks!
$highest = 0;
$highest_id = 0;
foreach($array as $a) {
if($a['like_count'] > $highest) {
$highest = $a['like_count'];
$highest_id = $a['id'];
}
}
Hope I understood you correctly :)
This looks like data retrieved from a database. If so, use the ORDER BY like_count DESC clause in the SQL.
The ID of the post with the most likes will then be at $posts[0]['id'] before you sort by your other method.
very easy task, you loop through your posts.
function get_max_like_post($posts) {
$max_like = 0;
$max_like_post = array();
foreach ($posts as $post) {
if ($post['like_count'] > $max_like) {
$max_like = $post['like_count'];
$max_like_post = $post;
}
}
return $max_like_post['id']
}
You could use usort.
$posts = array(
array('id' => 161, 'like_count' => 0),
array('id' => 162, 'like_count' => 6),
array('id' => 4, 'like_count' => 2),
);
function like_sort($a, $b) {
if ($a['like_count'] == $b['like_count']) {
return 0;
}
return ($a['like_count'] > $b['like_count']) ? -1 : 1;
}
usort($posts, 'like_sort');
// The first element in the array is now the one with the highest like_count.
echo $posts[0]['id']; // 162
Try this:
usort($posts, function($item) { return -$item['like_count']; });
$id = empty($posts) ? null : $posts[0]['id'];
Where $posts is the input array.
Explanation:
first you sort the posts by like count in decreasing fashion
then you get the top post id if there any posts, null otherwise.
What's good about this solution is that you can also select first n posts.
$highest_post_likes = 0;
$highest_post_id = 0;
for($i = 0; $i < sizeof($posts); $i++) {
if ( $posts[$i][like_count] > $highest_post_likes ) {
$highest_post_likes = $posts[$i][like_count];
$highest_post_id = $i;
}
}
// now you can use $posts[$highest_post_id]
Is those datas came from a database like MySQL? If is it, the simpliest solution is to put an "ORDER BY".
You can also make seperate the 'like_count' array keeping the same key than your first array and doing a asort (http://www.php.net/manual/fr/function.asort.php). You will have the key of the highest like count.
You can sort the array in descending order based on like_count and then pick up the id for the first array element.
You can use max function to get the highest value of likes:
foreach ($posts as $post){
$max[]=$post['like_count'];
}
echo max($max['id']);

PHP MySQL building a 3 Tier multi dimensional array

So I have my query, its returning results as expect all is swell, except today my designer through in a wrench. Which seems to be throwing me off my game a bit, maybe its cause Im to tired who knows, anyway..
I am to create a 3 tier array
primary category, sub category (which can have multiples per primary), and the item list per sub category which could be 1 to 100 items.
I've tried foreach, while, for loops. All typically starting with $final = array(); then the loop below that.
trying to build arrays like:
$final[$row['primary]][$row['sub']][] = $row['item]
$final[$row['primary]][$row['sub']] = $row['item]
I've tried defining them each as there own array to use array_push() on. And various other tactics and I am failing horribly. I need a fresh minded person to help me out here. From what type of loop would best suit my need to how I can construct my array(s) to build out according to plan.
The Desired outcome would be
array(
primary = array
(
sub = array
(
itemA,
itemB,
itemC
),
sub = array
(
itemA,
itemB,
itemC
),
),
primary = array
(
sub = array
(
itemA,
itemB,
itemC
),
sub = array
(
itemA,
itemB,
itemC
),
),
)
Something like this during treatment of your request :
if (!array_key_exists($row['primary'], $final)) {
$final[$row['primary']] = array();
}
if (!array_key_exists($row['sub'], $final[$row['primary']])) {
$final[$row['primary']][$row['sub']] = array();
}
$final[$row['primary']][$row['sub']][] = $row['item'];
Something like this....
$final =
array(
'Primary1'=>array(
'Sub1'=>array("Item1", "Item2"),
'Sub2'=>array("Item3", "Item4")
),
'Primary2'=>array(
'Sub3'=>array("Item5", "Item6"),
'Sub4'=>array("Item7", "Item8")
),
);
You can do it using array_push but it's not that easy since you really want an associative array and array_push doesn't work well with keys. You could certainly use it to add items to your sub-elements
array_push($final['Primary1']['Sub1'], "Some New Item");
If I understand you correctly, you want to fetch a couple of db relations into an PHP Array.
This is some example code how you can resolve that:
<?php
$output = array();
$i = 0;
// DB Query
while($categories) { // $categories is an db result
$output[$i] = $categories;
$ii = 0;
// DB Query
while($subcategories) { // $subcategories is an db result
$output[$i]['subcategories'][$ii] = $subcategories;
$iii = 0;
// DB Query
while($items) { // $items is an db result
$output[$i]['subcategories'][$ii]['items'][$iii] = $items;
$iii++;
}
$ii++;
}
$i++;
}
print_r($output);
?>

Categories