I have a huge, complicated issue in my php app. Here are the details:
I currently have this as my array (var dumped):
array (size=6)
0 => string '11/04/15' (length=8)
1 => string '15/04/15' (length=8)
2 => string '19/04/15' (length=8)
3 => string '1' (length=1)
4 => string '1' (length=1)
5 => string '3' (length=1)
But I want it displayed as:
array (size=6)
array(size=2)
string '11/04/15' (length=8)
string '1' (length=1)
array(size=2)
string '15/04/15' (length=8)
string '1' (length=1)
array(size=2)
string '19/04/15' (length=8)
string '3' (length=1)
As you can see I would like to add sub arrays, reorder the structure and remove the keys. The starter array values change so there could be more dates/less dates and numbers. Also the its linked, the key 0 should be bulked with key 3 and key 1 bulked with key 4 etc. I think that's enough information.
PS: I'm trying to arrange the data for Chart PHP's Bar Graph (http://www.chartphp.com/).
My approach would be the following:
Go through the array values with a foreach-loop and find out when the first number starts (in this case, it's the 4. element)
Save the number inside of a variable.
Create a new array
Go through the old array again and get the pairs, then push them into the new array.
The code would be similar to this:
<?
$old = array("date1","date2","date3",1,2,3);
$n = null;
foreach($old as $k => $v){
if(/*CHECK HERE IF $v is NOT A DATE anymore*/){
$n = $k;
break;
}
}
$new = array();
foreach($old as $k => $v){
if($k < $n){
$temp = array($v, $old[$k+$n]);
array_push($new, $temp);
}
}
var_dump ($new);
?>
This should work for you:
Since it is pretty obvious I'm going to assume, that the pattern behind your expected results should be to combine the numbers with the dates which are sorted ASC.
So here I first get all dates into an array with preg_grep(). Then I also get the numbers by getting the array_diff() from the original array and the dates array.
Then I sort both arrays ASC and the $dates array I sort with usort() where I compare the timestampes which I get with strtotime() and the $numbers array I sort simply with sort().
At the end I simply loop through both arrays with array_map() where I then create the expected result.
<?php
$arr = [
"19/04/15",
"11/04/15",
"15/04/15",
"3",
"1",
"1",
];
$dates = preg_grep("/\d{2}\/\d{2}\/\d{2}/", $arr);
$numbers = array_diff($arr, $dates);
sort($numbers);
usort($dates, function($a, $b){
if(strtotime($a) == strtotime($b))
return 0;
return strtotime($a) < strtotime($b) ? 1 : -1;
});
$result = array_map(function($v1, $v2){
return [$v1, $v2];
}, $dates, $numbers);
print_r($result);
?>
output:
Array
(
[0] => Array
(
[0] => 11/04/15
[1] => 1
)
[1] => Array
(
[0] => 15/04/15
[1] => 1
)
[2] => Array
(
[0] => 19/04/15
[1] => 3
)
)
Related
Im trying to count how many times a delivery date is in my array but i seem to only be able to count the first level.
array (size=48)
'2000-01-01' =>
array (size=2)
'date' => string '2000-01-01' (length=10)
0 =>
array (size=2)
'van' => string '0' (length=1)
0 =>
array (size=619)
'drop' => string '0' (length=1)
0 =>
array (size=29)
'id' => string '18137' (length=5)
'order_number' => string '13550' (length=5)
'reference' => string '' (length=0)
'delivery_date' => string '2000-01-01' (length=10)
I've tried:
$counts = array_count_values(array_flip(array_column($output, 'delivery_date')));
and
$array = array_map(function($element){
return $element['delivery_date'];
}, $output);
$array2 = (array_count_values($array));
print_r($array2);
in the end i either end up with a array to string error or the value 1.
how Would i go about counting these?
Thanks.
You could make use of array_walk_recursive and increment an array value every time the delivery_date key is present in the array at any level:
$counts = [];
array_walk_recursive(
$output,
static function ($value, string $key) use (&$counts): void {
if ($key === 'delivery_date') {
$counts[$value] = ($counts[$value] ?? 0) + 1;
}
}
);
I have the following two stdClass array from a loop. Now I need to merge them when when the key 'id' matches.
array (size=1)
0 =>
object(stdClass)[28]
public 'id' => string '78' (length=2)
public 'quantity' => string '5' (length=1)
array (size=1)
1 =>
object(stdClass)[31]
public 'product_id' => string '78' (length=2)
public 'quantity' => string '1' (length=1)
So the final array become
array (size=1)
1 =>
object(stdClass)[31]
public 'product_id' => string '78' (length=2)
public 'quantity' => string '6' (length=1)
Any help on how to do that ? I decode the original data using json_decode from [{"id":"78","quantity":"1"}] this format of data.
If you add an extra parameter to the json_decode, you can get the data as an associative array, which is much easier to work with. I've done a couple of versions ( the first is PHP 7 ), pick one which works with your system.
<?php
error_reporting ( E_ALL );
ini_set ( 'display_errors', 1 );
$arr1 = json_decode('[{"id":"78","quantity":"1"}, {"id":"79","quantity":"3"}]', true);
$arr2 = json_decode('[{"id":"78","quantity":"5"}]', true);
$arr3 = array_merge($arr1, $arr2);
// V7
$result = [];
foreach ( $arr3 as $element ) {
$result[$element['id']] = ($result[$element['id']]??0)
+ $element['quantity'];
}
print_r($result);
// Prior to V7
$result = array();
foreach ( $arr3 as $element ) {
if ( !isset($result[$element['id']]) ){
$result[$element['id']] = 0;
}
$result[$element['id']] += $element['quantity'];
}
print_r($result);
I've added another element to show how this adds up, but the output of this is...
Array
(
[78] => 6
[79] => 3
)
Array
(
[78] => 6
[79] => 3
)
Here is a solution that maintains the format in your original question.
It also uses array_reduce which is a concise way to process an array.
<?php
$input1 = '[{"id":"78","quantity":"7800"},
{"id":"79","quantity":"7900"},
{"id":"80","quantity":"8000"}]';
$input2 = '[{"id":"78","quantity":"6"},
{"id":"79","quantity":"8"},
{"id":"80","quantity":"6"},
{"id":"81","quantity":"7"}]';
$input1Arr = json_decode($input1);
$input2Arr = json_decode($input2);
$combinedArrays = array_merge($input1Arr, $input2Arr);
echo "combinedArrays = " . print_r($combinedArrays, true) . "\n";
$result = array_reduce($combinedArrays,
function($intermediateResult, $item){
if ( ! array_key_exists($item->id, $intermediateResult) ) {
// First time encountering an object with this id
$intermediateResult[$item->id] = $item;
}
else {
// We have an object with this id already so just add the quantity
$intermediateResult[$item->id]->quantity += $item->quantity;
}
return $intermediateResult;
}, []);
// Get the values from the result array
print_r(array_values($result));
I would like to turn the following string into an array:
prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined
INTO
array(
[prijs] => Array
(
[0] => 0
[1] => 209
)
[orderby] => Array
(
[0] => price
)
[order] => Array
(
[0] => undefined
)
[posts_per_page] => Array
(
[0] => undefined
)
)
Something like that. Is that possible?
Now I'm using some foreach loops, but that's not so fast and ideal like a RegEx.
It's a script which needs to load as fast as possible, so every bit of improvement in the code may help.
The amount of arrays can be variable. But it will always be 2 levels deep, like above. And just one main array.
You don't need REGEX for this. The string you have shown looks like a URL query string, in which case $_GET will already hold the values you need:-
var_dump($_GET);
Should give you:-
array (size=4)
'prijs' => string '0,209' (length=5)
'orderby' => string 'price' (length=5)
'order' => string 'undefined' (length=9)
'posts_per_page' => string 'undefined' (length=9)
Otherwise you can use parse_string().
$values = array();
parse_str('prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined', $values);
var_dump($values);
Output:
array (size=4)
'prijs' => string '0,209' (length=5)
'orderby' => string 'price' (length=5)
'order' => string 'undefined' (length=9)
'posts_per_page' => string 'undefined' (length=9)
Looks like you're in need of array_walk as it should be faster than a foreach even if it does pretty much the same thing it does it at a lower level.
as vascowhite suggested you can use $_GET if you have it or parse_str() to get an initial array, after that:
array_walk($array, function(&$n) {
$n = explode(',', $n);
});
Live code: http://3v4l.org/YfuKs
Results in exactly what you want (always having arrays instead of CSV strings):
Array
(
[prijs] => Array
(
[0] => 0
[1] => 209
)
[orderby] => Array
(
[0] => price
)
[order] => Array
(
[0] => undefined
)
[posts_per_page] => Array
(
[0] => undefined
)
)
PS: instead of explode() you can use preg_split('/,/', $n) since you mentioned RegEx and see which one is faster for you
$str = 'prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined';
$array = preg_split('/[&]/' , $str);
foreach ($array as $a)
{
$a = preg_split('/[=]/' , $a);
$a[1] = preg_split('/[,]/' , $a[1]);
}
var_dump($array);
Well, you can use something like this:
<?php
parse_str("prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined",$myArray);
$myArray['prijs'] = explode(",", $myArray['prijs']);
$myArray['orderby'] = explode(",", $myArray['orderby']);
$myArray['order'] = explode(",", $myArray['order']);
$myArray['posts_per_page'] = explode(",", $myArray['posts_per_page']);
print_r($myArray);
?>
function urlSplitter($input)
{
$step1Array = explode('&', $input);
$result = array();
foreach($step1Array as $element)
{
$parts = explode("=", $element);
$result[$parts[0]] = explode(",", $parts[1]);
}
return $result;
}
$result = urlSplitter("prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined");
var_dump($result);
I have 2 arrays and I would like to delete everything in the first array that is in the second array. In thise case I would like to delete "ibomber" and "apphero" in array one. I tried something with unset, but it doesn't look like it works.
array (size=5)
0 => string 'Air Hippo' (length=9)
1 => string 'iBomber Defense Pacific' (length=23)
3 => string 'AppHero' (length=7)
5 => string 'Pillboxie' (length=9)
6 => string 'Monogram' (length=8)
array (size=2)
0 => string ' iBomber Defense Pacific' (length=24)
1 => string ' AppHero' (length=8)
This is what I tried:
foreach ($_SESSION["appsarray"] as $k=>$v)
{
foreach ($_SESSION["finalapps"] as $k2=>$v2)
{
if ($v == $v2)
{
unset ($_SESSION["appsarray"][$k]);
}
}
}
Session appsarray is my first array and session finalapps is my second array.
Thanks!
function TrimmedStrCaseCmp($str1,$str2)
{
return strcasecmp(trim(str1),trim(str2));
}
$result = array_udiff(values,to_remove_from_values,'TrimmedStrCaseCmp');
http://php.net/manual/en/function.array-udiff.php
You're looking for array_diff i.e.;
$appsarray = array('Air Hippo','iBomber Defense Pacific','AppHero','Pillboxie','Monogram');
$finalapps = array('iBomber Defense Pacific','AppHero');
$result = array_diff($appsarray,$finalapps);
print_r($result);
Will output;
Array ( [0] => Air Hippo [3] => Pillboxie [4] => Monogram )
I want to generate a list of the second level of keys used. Each record does not contain all of the same keys. But I need to know what all of the keys are. array_keys() doesn't work, it only returns a list of numbers.
Essentially the output Im looking for is:
action, id, validate, Base, Ebase, Ftype, Qty, Type, Label, Unit
I have a large multi-dimensional array that follows the format:
Array
(
[0] => Array
(
[action] => A
[id] => 1
[validate] => yes
[Base] => Array
(
[id] => 2945
)
[EBase] => Array
(
[id] => 398
)
[Qty] => 1
[Type] => Array
(
[id] => 12027
)
[Label] => asfhjaflksdkfhalsdfasdfasdf
[Unit] => asdfas
)
[1] => Array
(
[action] => A
[id] => 2
[validate] => yes
[Base] => Array
(
[id] => 1986
)
[FType] => Array
(
[id] => 6
)
[Qty] => 1
[Type] => Array
(
[id] => 13835
)
[Label] => asdssdasasdf
[Unit] => asdger
)
)
Thanks for the help!
<?php
// Gets a list of all the 2nd-level keys in the array
function getL2Keys($array)
{
$result = array();
foreach($array as $sub) {
$result = array_merge($result, $sub);
}
return array_keys($result);
}
?>
edit: removed superfluous array_reverse() function
array_keys(call_user_func_array('array_merge', $a));
Merge all values and retrieve the resulting keys.
One liner:
$keys=array_unique(array_reduce(array_map('array_keys',$data),'array_merge',[]));
Or in a function:
function get_array_children_keys($data) {
return array_unique(
array_reduce(array_map('array_keys', $data), 'array_merge', [])
);
}
Now lets break this down with an example, here is some sample data:
[
['key1' => 0],
['key1' => 0, 'key2' => 0],
['key3' => 0]
]
Starting with the inner most function, we run array_map with the array_keys function:
array_map('array_keys', $data)
This gives us the keys of from all child arrays
[
['key1'],
['key1', 'key2'],
['key3']
]
Then we run the array_reduce on the data with the array_merge callback and an empty array as the initial value:
array_reduce(..., 'array_merge', []);
This converts our multiple arrays into 1 flat array:
[
'key1',
'key1',
'key2',
'key3'
]
Now we strip out our duplicates with array_unique:
array_unique(...)
And end up with all our keys:
[
'key1',
'key2',
'key3'
]
foreach($bigArray as $array){
foreach($array as $key=>$value){
echo $key;
}
}
That should do what you want.
What about something like this :
$your_keys = array_keys($your_array[0]);
Of course, this is considering all sub-arrays have the same keys ; in this case, you only need the keys of the first sub-array (no need to iterate over all first-level sub-arrays, I guess)
And, as a shortened / simplified example :
$your_array = array(
array(
'action' => 'A',
'id' => 1,
'base' => array('id' => 145),
),
array(
'action' => 'B',
'id' => 2,
'base' => array('id' => 145),
),
array(
'action' => 'C',
'id' => 3,
'base' => array('id' => 145),
)
);
$your_keys = array_keys($your_array[0]);
var_dump($your_keys);
Will get you :
array
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'base' (length=4)
You can the use implode to get the string you asked for :
echo implode(', ', $your_keys);
will get you :
action, id, base
ie, the list of the keys of the first sub-array.
function __getAll2Keys($array_val){
$result = array();
$firstKeys = array_keys($array_val);
for($i=0;$i<count($firstKeys);$i++){
$key = $firstKeys[$i];
$result = array_merge($result,array_keys($array_val[$key]));
}
return $result;
}
try this function. It will return as you want.
While #raise answers provides a shortcut, it fails with numeric keys. The following should resolve this:
$secondKeys=array_unique(call_user_func_array('array_merge', array_map('array_keys',$a)));
array_map('array_keys',$a) : Loop through while getting the keys
...'array_merge'... : Merge the keys array
array_unique(... : (optional) Get unique keys.
I hope it helps someone.
UPDATE:
Alternatively you can use
$secondKeys=array_unique(array_merge(...array_map('array_keys', $a)));
That provides same answer as above, and much faster.
My proposal, similar to this answer but faster and using spread operator (PHP 5.6+).
array_merge(...array_values($fields))
if you want move names to array values and reset keys to 0..n just use array_keys in last step.
array_keys(array_merge(...array_values($fields)))
Maybe you can use array_map function, which allows you to avoid array iteration and return an array with the keys you need as values.
will be like this
$newArray = array_map(function($value){return array_keys($value);},$yourArray);
var_dump($newArray);
array (size=2)
0 =>
array (size=9)
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'validate' (length=8)
3 => string 'Base' (length=4)
4 => string 'EBase' (length=5)
5 => string 'Qty' (length=3)
6 => string 'Type' (length=4)
7 => string 'Label' (length=5)
8 => string 'Unit' (length=4)
1 =>
array (size=9)
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'validate' (length=8)
3 => string 'Base' (length=4)
4 => string 'FType' (length=5)
5 => string 'Qty' (length=3)
6 => string 'Type' (length=4)
7 => string 'Label' (length=5)
8 => string 'Unit' (length=4)
With this function you can get all keys from a multidimensional array
function arrayKeys($array, &$keys = array()) {
foreach ($array as $key => $value) {
$keys[] = $key;
if (is_array($value)) {
$this->arrayKeys($value, $keys);
}
}
return $keys;
}
Only if all records have the same keys you could do:
$firstItem = reset($array);
$keys = array_keys($firstItem);
Obviously, this is not the correct answer to this specific question, where the records have different keys. But this might be the question you find when looking how to retrieve second level keys from an array where all keys are the same (I did). If all the record have the same keys, you can simply use the first item in the array with reset() and get the keys from the first item with array_keys().