how to get number out of an array key - php

I have the following array:
Array
(
[Ingredient 1 Amount] => Array
(
[0] => 2
)
[Ingredient 1] => Array
(
[0] => lemon juice (t fresh-squeezed)
)
[Ingredient 2 Amount] => Array
(
[0] => 3
)
[Ingredient 2] => Array
(
[0] => 1/2 cups peeled and diced potatoes
)
[Ingredient 3 Amount] => Array
(
[0] => 1/3
)
[Ingredient 3 Size] => Array
(
[0] => cup
)
[Ingredient 3] => Array
(
[0] => diced celery
)
[Ingredient 4 Amount] => Array
(
[0] => 1/3
)
[Ingredient 4 Size] => Array
(
[0] => cup
)
[Ingredient 4] => Array
(
[0] => finely chopped onion
)
[Ingredient 5 Amount] => Array
(
[0] => 5
)
[Ingredient 5 Size] => Array
(
[0] => tablespoons
)
[Ingredient 5] => Array
(
[0] => pickles
)
)
Each ingredient set consists of Amount, Size and just the Default. There may be one of each or there may be some missing, so I can't just count the array and divide by 3. I need to know how many ingredient sets are in the array. This is shown by the last ingredient set, so in this case I would want the number "5". How would I go about getting that?
--EDIT--
The array is being built from custom post fields in wordpress. It's what I get back from
$post_meta = get_post_meta($id);

In my opinion you should re-structure you're array. It is not optimised.
Try something along the lines of (this is psuedo code to give the idea)
[Ingredient 1] => Array
(
[type] => lemon juice (t fresh-squeezed),
[Amount] => lemon juice (t fresh-squeezed),
[Size] => lemon juice (t fresh-squeezed)
)

As I've mentioned in my comments restructuring your array would be far better, as your current structure isn't helpful for what you want to do. However, assuming that isn't an option this is what to do:
$key = end(array_keys($array));
$num = substr($key, 11);
You can see an example of this in work here on eval.in.
This will work if the last key won't always be the one you want:
$keyArr = array_keys($array);
$keyRev = array_reverse($keyArr);
foreach($keyRev as $key) {
if(stripos($key, 'amount') === FALSE && stripos($key, 'size') === FALSE) {
$num = substr($key, 11);
break;
}
}
echo $num;
You can see an example of this in work here on eval.in.

you can find maximum like this
$max = 0;
foreach($array as $key => $value) {
if(intval(str_replace("Ingredient ", "", $key)) > $max) {
$max = intval(str_replace("Ingredient ", "", $key));
}
}
NOTICE: as Styphon mentioned in comments if you want to get last element number, it's not necessary to loop through whole array, only process last element

$a = array(
array(['ingediant1'] =>
array(
'amount' => 1,
'description' => 'whatever'
)
)
);
$amount = 0;
foreach ($a as $ingediant => $info) {
$amount += $info['amount'];
}
If you'd restructure your array to something like I did, you should be able to get the total amount of ingredients easy.

Related

Comparing in an Array: If two highest value exists, then compare the other value

Suppose I have an array like:
array( [0] => array([item]=>apple [buy]=>50 [sell]=>30)
[1] => array([item]=>lemon [buy]=>50 [sell]=>60)
[2] => array([item]=>banana [buy]=>40 [sell]=>20)
[3] => array([item]=>orange [buy]=>20 [sell]=>30)
)
Currently I am using this script to check which item has the most buyer
function getMax($array, $val)
{
$max = 0;
foreach( $array as $k => $v )
{
$max = max( array( $max, $v[$val] ) );
}
return $max;
}
$highestBuy = getMax($thisArray, 'buy');
foreach($thisArray as $i=>element){
if($element['buy'] == $highestBuy){
$thisArray[$i]['highestBuy'] = 'yes';
} else {
$thisArray[$i]['highestBuy'] = 'no';
}
}
In this case, both apple and lemon will have highestBuy a yes value. But now I want to find out which item is the most popular by checking their sell if there are two or more same value of highestBuy. Which is the most simple or fastest way to make the output like:
array([0] => array([item]=>apple [buy]=>50 [sell]=>30 [mostPopular]=>no)
[1] => array([item]=>lemon [buy]=>50 [sell]=>60 [mostPopular]=>yes)
[2] => array([item]=>banana [buy]=>40 [sell]=>20 [mostPopular]=>no)
[3] => array([item]=>orange [buy]=>20 [sell]=>30 [mostPopular]=>no)
)
Thanks in advance.
EDIT:
What I want to do is:
find out the highest buy
If this value occur only once(which means there are one highest buy in the array) then push the [mostPouplar]=>yes into the array
If not(there are two or more same highest value), then find out the highest sell.
That's mean if the highest value is unique, it will stop doing further action. If not, it will keep going to find secondary highest value in an array. Is it possible to achieve this?
Sort array with your rules and take first element
$array = array( '0' => array('item'=>apple, 'buy'=>50 ,'sell'=>30),
'1' => array('item'=>lemon, 'buy'=>50, 'sell'=>60),
'2' => array('item'=>banana, 'buy'=>40, 'sell'=>20),
'3' => array('item'=>orange, 'buy'=>20 ,'sell'=>30)
);
usort($array,
function($a, $b) {
$res = $b['buy'] - $a['buy'];
if (!$res) $res = $b['sell'] - $a['sell'];
return $res; });
result:
Array (
[0] => Array ( [item] => lemon [buy] => 50 [sell] => 60 )
[1] => Array ( [item] => apple [buy] => 50 [sell] => 30 )
[2] => Array ( [item] => banana [buy] => 40 [sell] => 20 )
[3] => Array ( [item] => orange [buy] => 20 [sell] => 30 ) )
I had changed the getMax() to return the index of the most popular item
function getMax($array, $val, $val2)
{
$max_item = 0;
foreach( $array as $k => $v )
{
if($array[$max_item][$val] <= $v[$val] && $array[$max_item][$val2] <= $v[$val2])
$max_item = $k;
}
return $max_item;
}
$highestBuy = getMax($thisArray, 'buy', 'sell');
foreach($thisArray as $i => $element){
$thisArray[$i]['mostPopular'] = ($i == $highestBuy) ? 'yes' : 'no';
}

Looping through and clearing arrays

I have arrays within arrays, all with varying amounts of information. My CSV table currently has the fields Name, Email, and Phone Number.
Below is my array;
Array
(
[0] => Array
(
[0] => Name
[1] => Email
[2] => Phone Number
)
[1] => Array
(
[0] => Mick
[1] => mick#mick.com
[2] => 01234 324234
)
[2] => Array
(
[0] => james
[1] => james#james.com
[2] =>
)
[3] => Array
(
[0] => reg
[1] => reg#reg.com
[2] => 10293 467289
)
)
I wish to loop through and remove these null values and combine the Email and Phone Number into Info end up with an array which resembles
Array
(
[0] => Array
(
[0] => Name
[1] => Info
)
[1] => Array
(
[0] => Mick
[1] => mick#mick.com + 01234 324234
)
[2] => Array
(
[0] => james
[1] => james#james.com
)
[3] => Array
(
[0] => reg
[1] => reg#reg.com + 10293 467289
)
)
Here is my current script, I am recienving the error;
<b>Warning</b>: array_filter() expects parameter 2 to be a valid callback, no array or string given in <b>C:\Users\Lydia\Documents\XAMPP\htdocs\CSV.php</b> on line <b>21</b><br />
every time that I loop through the changeRow() function, any help greatly appreciated
index.php
<?php
include 'CSV.php';
header('Content-type: text/plain');
$file = read_csv('Book1.csv');
$input = changeRow($file);
CSV.php
....
....
function changeRow($rows){
$len = count($rows);
for($i = 0; $i < $len; $i++){
$rows = array_filter($rows[0],0);
}
}
Can use array_map() instead of foreach(). Example:
$file = read_csv('Book1.csv');
$input = array_map(function($v){
$phone = (isset($v[2]) && $v[2]) ? ' + '. $v[2] : '';
return array($v[0], $phone);
},$file );
if(isset($result[0][1])) $result[0][1] = 'Info';
print '<pre>';
print_r($input);
print '</pre>';
I'll provide two methods that output the requested array structure. (PHP Demo Link) These methods iterate the array, check if the iteration is dealing with the "column heading" subarray or not, then conditionally appending the value from subarray element [2] to subarray element [1] using + as glue.
Method #1: foreach()
foreach($array as $index=>$item){
if(!$index){
$result[]=['Name','Info'];
}else{
$result[]=[$item[0],$item[1].(strlen($item[2])?" + $item[2]":'')];
}
}
var_export($result);
Method #2 array_map()
var_export(
array_map(function($index,$item){
if(!$index){
return ['Name','Info'];
}else{
return [$item[0],$item[1].(strlen($item[2])?" + $item[2]":'')];
}
},array_keys($array),$array)
);
Output: (from either method)
array (
0 =>
array (
0 => 'Name',
1 => 'Info',
),
1 =>
array (
0 => 'Mick',
1 => 'mick#mick.com + 01234 324234',
),
2 =>
array (
0 => 'james',
1 => 'james#james.com',
),
3 =>
array (
0 => 'reg',
1 => 'reg#reg.com + 10293 467289',
),
)
ps. If you want to remove the $index==0 check that is iterated each time, you can manually overwrite the first subarray after the loop is finished like this: (PHP Demo Link) *this just means you will be "writing" data to the first subarray twice.
foreach($array as $item){
$result[]=[$item[0],$item[1].(strlen($item[2])?" + $item[2]":'')];
}
$result[0]=['Name','Info'];
var_export($result);
or
$result=array_map(function($item){return [$item[0],$item[1].(strlen($item[2])?" + $item[2]":'')];},$array);
$result[0]=['Name','Info'];
var_export($result);
pps. "Passing by Reference" can be used for this task, but I've elected not to use &$array because it can risk causing trouble "downscript" and many developers advise against using it until other methods are inadequate. Here is what that can look like: (PHP Demo Link)
foreach($array as &$item){
if(strlen($item[2])) $item[1].=" + $item[2]";
unset($item[2]);
}
$array[0]=['Name','Info'];
var_export($array);
unset($item); // var_export($item); // ($item = NULL)

Parsing array values into multidimensional array

I have some data I retrieve from a JSON feed that currently is being parsed into an array like this: (simplifying for demonstration purposes)
So pretty much an array returns a movie theater name, with the showtimes associated with that particular theater.
[0] => American Theater
[1] => 2014-06-04T13:10
[2] => 2014-06-04T15:10
[3] => Grand Theater
[4] => 2014-06-04T15:30
[5] => 2014-06-04T19:10
How would I parse this array to be multidimensional, for instance:
Array
(
[0] => Array
(
[theater] => Array
(
[name] => American Theater
)
[showtimes] => Array
(
[1] => 2014-06-04T13:10
[2] => 2014-06-04T15:10
)
)
[1] => Array
(
[theater] => Array
(
[name] => Grand Theater
)
[showtimes] => Array
(
[1] => 2014-06-04T15:30
[2] => 2014-06-04T19:10
)
)
)
I'm assuming you're trying to access some api and have no control over how the data is passed back to you? If you do then the API should be responsible for returning a sensible schema.
But if you're forced to work with this array and the amount of showtimes are unknown to you, then you can do something like this:
$array = array(
'American Theater',
'2014-06-04T13:10',
'2014-06-04T15:10',
'Grand Theater',
'2014-06-04T15:30',
'2014-06-04T19:10'
);
$i = 0;
foreach ($array as $key => $value) {
if (strtotime($value)) {
$theaters[$i - 1]['showtimes'][] = $value;
}
else {
$theaters[$i]['theater']['name'] = $value;
$i++;
}
}
Outcome
To walk you through it, $array is whatever the returned dataset is. We set an index in the $i value and want to only increment it if we determine we've detected a theater name. Within the loop we first try to determine if the string can be converted to a php time value. If it cannot we add the theater name to our new schema structure, and increment our index value. Since times are always added to theater names, we are expecting the first index number to always be one higher than what we want to add the showtime to.
This will fail to be accurate in cases when a theater name is convertible to a time value in such cases like Next Month. There are a couple of other ways to solve this with regex or by inspecting the string for certain characters and their position since the time format will remain the same.
You could replace the strtotime() with:
$str = str_split($value);
if (($str[4] && $str[7]) == '-' && $str[10] == 'T' && $str[13] == ':' ) {
$theaters[$i - 1]['showtimes'][] = $value;
}
If you want such structure, you need to create a new copy of it. You may also need to chunk/group them by three's using array_chunk first, and then, from there, you can loop it now and start creating the desired format.
Consider this example:
$old_values = array('American Theater', '2014-06-04T13:10', '2014-06-04T15:10', 'Grand Theater', '2014-06-04T15:30', '2014-06-04T19:10');
$old_values = array_chunk($old_values, 3);
$new_values = array();
foreach($old_values as $key => $value) {
$new_values[] = array(
'theater' => array('name' => $value[0]),
'showtimes' => array(1 => $value[1], 2 => $value[2]),
);
}
Edit: As mentioned, one theater can have many showtimes, therefore this current solution will fail. This may be an alternative (you may need to check each element if its a theater name or a date). Consider this example:
$old_values = array(
'American Theater',
'2014-06-04T13:10',
'2014-06-04T15:10',
'Grand Theater',
'2014-06-04T15:30',
'2014-06-04T19:10',
'Magic Johnson Theater',
'2014-06-04T19:10',
'2014-06-04T19:10',
'2014-06-04T19:10',
'Mall of America Theater',
'2014-06-04T19:10',
'2014-06-04T19:10',
'2014-06-04T19:10',
'2014-06-04T19:10',
);
$new_values = array();
$current_key = 0;
foreach($old_values as $key => $value) {
$current_value = $value;
$pieces = explode('T', $current_value);
$dates = explode('-', $pieces[0]);
if(count($dates) == 3) {
$new_values[$current_key]['showtimes'][] = $current_value;
} else {
$current_key++;
$new_values[$current_key]['theater']['name'] = $current_value;
}
}
Sample Output:
Array
(
[1] => Array
(
[theater] => Array
(
[name] => American Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T13:10
[1] => 2014-06-04T15:10
)
)
[2] => Array
(
[theater] => Array
(
[name] => Grand Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T15:30
[1] => 2014-06-04T19:10
)
)
[3] => Array
(
[theater] => Array
(
[name] => Magic Johnson Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T19:10
[1] => 2014-06-04T19:10
[2] => 2014-06-04T19:10
)
)
[4] => Array
(
[theater] => Array
(
[name] => Mall of America Theater
)
[showtimes] => Array
(
[0] => 2014-06-04T19:10
[1] => 2014-06-04T19:10
[2] => 2014-06-04T19:10
[3] => 2014-06-04T19:10
)
)
)
Sample Fiddle

Convert complex numerical array to associative array

I have an array data that look like this :
Array (
[0] => Array (
[0] => Name:
[1] => John W.
[2] => Registration ID:
[3] => 36
)
[1] => Array (
[0] =>Age:
[1] => 35
[2] => Height:
[3] => 5'11"
)
[3] => Array (
[0] => Sex:
[1] => M
[2] => Weight:
[3] => 200lbs
)
[4] => Array (
[0] => Address
)
[5] => Array (
[0] => 6824 crestwood dr delphi, IN 46923
))
And I want to convert it to associative array like this :
Array(
['Name']=> John W.
['Registration ID']=> 36
['Age']=> 35
['Height'] => 5'11''
['Sex']=>M
['Weight']=>200lbs
['Address']=>6824 crestwood dr delphi, IN 46923
)
I have no idea at all how to do this, since the supposed to be array column header were also in sequence, so it makes difficult to convert this array.
Any help I appreciate, thx.
Given your origin array is called $origin , you can do it like this:
$merged = array();
foreach($origin as $val) {
$merged = array_merge($merged, $val);
}
$tot = count($merged) - 1;
for ($i=0;$i<$tot;$i+=2) {
$result[$merged[$i]] = $merged[$i+1];
}
var_dump($result); // To test the resulting array
Firstly, I use array_merge() to flatten the $origin array to only one dimension/depth, so we later iterate it (stepping each 2 items per iteration) and assigning each pair of items ($i and $i+1) to the resulting array.
Looks like, for the first 3 children, you can just assign the even value to the previous element as key. Then, assign the fourth one as key for fifth element.
$result = array();
foreach ($array as $key => $value)
{
if ($key < 4) {
$elements = array_values($value);
$result[$elements[0]] = $elements[1];
$result[$elements[2]] = $elements[3];
}
if ($key == 4)
$fifthkey = $value;
if ($key == 5)
$result[$fifthkey] = $value;
}
Also, note that you have to escape your height string quotes.

Group and Sum this Array

I have an array that's output is this:
Array ( [winners] =>
Array ( [0] => Gold Member
[1] => CROTCH SNIFFER
[2] => TEAM #1 )
[prizeTotal] => 20 )
Array ( [winners] =>
Array ( [0] => TEAM #1
[1] => CROTCH SNIFFER )
[prizeTotal] => 60 )
Array ( [winners] =>
Array ( [0] => Gold Member
[1] => TEAM #1 )
[prizeTotal] => 30 )
Array ( [winners] =>
Array ( [0] => TEAM #1
[1] => TEAM #2
[2] => SCREW-NUT-BOLT )
[prizeTotal] => 90 )
Please forgive the names...it's not my DB.
I can not change the way the array is show here.
With that being said how can I group and sum?
1. For each winners array there is a prizeTotal below the team names. That prize total should be the value of each teamName above it.
Example
Array ( [winners] =>
Array ( [0] => Gold Member
[1] => CROTCH SNIFFER
[2] => TEAM #1 )
[prizeTotal] => 20 )
Gold Member should have 20
CROTCH SNIFFER should have 20
TEAM #1 should have 20 AND
Array ( [winners] =>
Array ( [0] => TEAM #1
[1] => CROTCH SNIFFER )
[prizeTotal] => 60 )
TEAM #1 should have 60
CROTCH SNIFFER sould have 60....etc....
Then I want to group by team name and sum so that I can display...
CROTCH SNIFFER = 80
Gold Member = 50
TEAM #1 = 200
Team #2 = 90.
Thanks in advance...
Assuming you can collect all your arrays into one i.e. :
$arrays = array($array1,$array2,....,$arrayn);
then
$grouping = array();
foreach($arrays AS $array)
{
foreach($array['winners'] AS $k=>$v)
{
//check if the array key is a number, will contain a team, and if that
//them is not alreay listed
if(is_numeric($k) && !array_key_exists($v,$grouping))
$grouping[$v] = 0;
//sum the prize to the team's sum
$grouping[$v] += intval($array['winners']['prizeTotal']);
}
}
//the following is just for debugging
print_r($grouping);
this should produce something like:
$grouping[TEAM #1] = 200
$grouping[TEAM #2] = 90
$grouping[CROTCH SNIFFER] = 200
...
You need to make a new array to hold your results, then for each of your existing arrays, check if you're already processed one for that team
If you have, then simply add the prizeTotal to the prizeTotal stored in your new array's entry for that team.
If not, simply add the team's entry to your new array.
I have made a function that imitates mysql SUM() and GROUP BY. I hope it will fit your needs:
$in_a = array(
array("a" => 0,"b"=>0,"s"=> 1),
array("a" => 0,"b"=>0,"s"=> 2),
array("a" => 1,"b"=>1,"s"=> 1),
array("a" => 0,"b"=>1,"s"=> 1),
array("a" => 0,"b"=>1,"s"=> 1),
array("a" => 1,"b"=>0,"s"=> 1),
array("a" => 0,"b"=>1,"s"=> 1),
array("a" => 1,"b"=>1,"s"=> 1),
array("a" => 1,"b"=>0,"s"=> 1),
);//input array exaple
$group_by_a = array("a","b");//input array will be grouped by these
$sum_a = array("s"); //'s' values of input will be summed
$out_a = array(); //this is the output array
foreach($in_a as $in_i => $in)
{
$add = false;
foreach($out_a as $out_i => $out)
{
$add = true;
foreach($group_by_a as $group_by)
if($in[$group_by] != $out[$group_by])
{
$add = false;
break;
}
if($add)
{
foreach($sum_a as $sum)
$out_a[$out_i][$sum] += $in[$sum];
break;
}
}
if(!$add)
{
foreach($group_by_a as $group_by)
$out_a[$in_i][$group_by] = $in[$group_by];
foreach($sum_a as $sum)
$out_a[$in_i][$sum] = $in[$sum];
}
}
the result:
Array
(
[0] => Array
(
[a] => 0
[b] => 0
[s] => 3
)
[2] => Array
(
[a] => 1
[b] => 1
[s] => 2
)
[3] => Array
(
[a] => 0
[b] => 1
[s] => 3
)
[5] => Array
(
[a] => 1
[b] => 0
[s] => 2
)
)

Categories