coming from an FP background and now learning PHP I'm naturally missing some beloved higher-order functions. I was wondering if there's anything like Clojure's partition-by in PHP. Here's the official description of what it does:
(partition-by f)(partition-by f coll)
Applies f [a function] to each value in coll, splitting it each time f
returns a new value. Returns a lazy seq of partitions. Returns a
stateful transducer when no collection is provided.
I don't really care about the lazy and transducer parts (which I guess are out of the question in PHP anyway, am I right?) What I need to do is tranform an array like this :
[["year" => 2019, "val" => "foo"],
["year" => 2019, "val" => "bar"],
["year" => 2020, "val" => "baz"],
["year" => 2020, "val" => "boo)"]]
into this:
[[["year" => 2019, "val" => "foo"],
["year" => 2019, "val" => "bar"]],
[["year" => 2020, "val" => "baz"],
["year" => 2020, "val" => "boo)"]]]
i.e. I want to group them by the result of a function like this:
function getYear($pair)
{
return $pair["year"];
}
I haven't tried yet to code something like this up myself, but I was wondering if anything like this exists in a functional lib (or even the core?) of PHP.
I don't think this exists as a language feature. At least I haven't or couldn't find anything.
However, (unless I misunderstood) this should give you the result you described, with the caveat that the initial array must first be sorted by the partition value:
$f = [
["year" => 2019, "val" => "foo"],
["year" => 2019, "val" => "bar"],
["year" => 2020, "val" => "baz"],
["year" => 2020, "val" => "boo)"]
];
var_dump(partitionMultidim($f, "year"));
function partitionMultidim(array $values, string $key):array{
$new = [];
$p = $values[0][$key]; // alternatively check if exists in loop and set if not
$partitionNum = 0;
foreach($values as $value){
// what is the current value?
$curPartitionVal = $value[$key]; // or getYear($b);
// has the value changed?
if ( $p !== $curPartitionVal ){
// set the next partition value
$p = $curPartitionVal;
// new partition index
$partitionNum++;
}
// add to the new array
$new[$partitionNum][] = $value;
}
return $new;
}
This does not exist as a language feature. However, there are ready classes that do the same. Example:
$f = [
["year" => 2020, "val" => "baz"],
["year" => 2019, "val" => "foo"],
["year" => 2019, "val" => "bar"],
["year" => 2020, "val" => "boo)"]
];
//https://github.com/jspit-de/tableArray
$newArr = tableArray::create($f)
->orderBy('year ASC,val ASC')
->fetchGroup(['year'])
;
//test output
echo '<pre>';
var_dump($newArr);
Output:
array(2) {
[2019]=>
array(2) {
[0]=>
array(2) {
["year"]=>
int(2019)
["val"]=>
string(3) "foo"
}
[1]=>
array(2) {
["year"]=>
int(2019)
["val"]=>
string(3) "bar"
}
}
[2020]=>
array(2) {
[2]=>
array(2) {
["year"]=>
int(2020)
["val"]=>
string(4) "boo)"
}
[3]=>
array(2) {
["year"]=>
int(2020)
["val"]=>
string(3) "baz"
}
}
}
Related
I have a multidimensional array
output_querys = array(2) { [0]=> array(5) { ["ID"]=> string(1) "2" ["Code"]=> string(6) "AWS001" ["BCode"]=> string(4) "B001" ["Des"]=> string(4) "loan" ["subCat"]=> string(3) "SWA" } [1]=> array(5) { ["ID"]=> string(1) "4" ["Code"]=> string(6) "AWS002" ["BCode"]=> string(4) "B002" ["Des"]=> string(3) "tax" ["subCat"]=> string(3) "PJA" } }
I want to get this to a variable and then save into dB.I have tried all the methods that has mentioned in related problems nothing worked.
Errors I got
1.trying non-object
2.Illegal string offset
what I was trying to do is
foreach($output_querys as $output_query){
$Pv_ID = $output_query->ID;
$Pv_Code = $output_query->Code;
$Pv_Description = $output_query->Des;
$data_final = array(id => $Pv_ID, code => $Pv_Code, des => $Pv_Description);
}
db->insert(abc, $data_final);
what is the problem here??.even i tried with json encode and still shows the "Illegal string offset"
$Pv_ID= json_decode($output_query['ID']);
$Pv_Code = json_encode($output_query['Code'],true);
$Pv_Description = json_encode($output_query['Des'],true);
I tried your given array and code
<?php
$output_querys = array(
0 => array(
"ID" => "2",
"Code" => "AWS001",
"BCode" => "B001",
"Des" => "loan",
"subCat" => "SWA"
),
1 => array(
"ID" => "4",
"Code" => "AWS002",
"BCode" => "B002",
"Des" => "tax",
"subCat" => "PJA"
)
);
foreach($output_querys as $output){
print_r($output['Code']); echo "\n";
}
?>
It is working fine on my end. Here's the working example
I think you need to do this as well, if you want to insert 1 by 1 then move the insert in foreach loop
foreach($output_querys as $output_query){
$Pv_ID = $output_query->ID;
$Pv_Code = $output_query->Code;
$Pv_Description = $output_query->Des;
$data_final = array(id => $Pv_ID, code => $Pv_Code, des => $Pv_Description);
db->insert(abc, $data_final);
}
How to foreach through a deeper array in PHP? I want to approach 'price' and list all prices below each other.
$addons = get_product_addons($product->get_id());
When I VAR_DUMP the $addons var, it outputs the below.
array(1) {
[0]=>
array(7) {
["name"]=>
string(8) "Afmeting"
["description"]=>
string(0) ""
["type"]=>
string(6) "select"
["position"]=>
int(0)
["options"]=>
array(10) {
[0]=>
array(5) {
["label"]=>
string(8) "70 x 200"
["price"]=>
string(0) "70.00"
["min"]=>
string(0)""
...
So I want to output this result:
70.00
60.00
Etcetera.. *All prices
I guess that piece of code is what you are looking for:
foreach($addons as $addon)
{
echo $addon["options"]["price"].PHP_EOL;
}
You do not need to use foreach to access nested elements of array. Just use it's key.
PHP_EOL is a constant containing newline for your OS. For web application use special formatting suitable for your page (<br> e.g.)
You can walk or foreach through the items:
<?php
$data =
[
[
'name' => 'orange',
'options' =>
[
'price' => '6.00'
]
],
[
'name' => 'banana',
'options' =>
[
'price' => '4.00'
]
]
];
array_walk($data, function($v) {
echo $v['options']['price'], "\n";
});
Output:
6.00
4.00
Or you could create an array of prices and iterate on that (here using short function syntax):
$prices = array_map(fn($v)=>$v['options']['price'], $data);
var_export($prices);
Output:
array (
0 => '6.00',
1 => '4.00',
)
I would like to know how I can get all the values of an array without having to manually access to each key to then get the value.
That is, I have this arrangement.
$user = [ "Id" => 123, "Name" => "Dave", "Age" => 25, "Country" => "US"];
I want to get the values 123, "Dave," 25, "US".
PHP has a function that does exactly what you need, which is array_values Return all the values of an array.
// e.g.
$user = [
"id" => 123,
"name" => "Dave",
"age" => 25,
"country" => "US"
];
print_r(array_values($user));
Result
Array
(
[0] => 123
[1] => Dave
[2] => 25
[3] => US
)
NOTE:
But beware of boolean values because if any value of the array is TRUE, array_values it will transform to 1 and if the value is FALSE will not return anything (it has the same behavior as the isset function)
YOu can get all the values without the keys and then use implode to make it into a single string
$array = array_values($user);
var_dump($array);
you will get
array(4) {
[0]=> int(123)
[1]=> string(4) "Dave"
[2]=> int(25)
[3]=> string(2) "US" }
If you want it as a string use
$comma_separated = implode(",", $user);
echo $comma_separated;
Result will be
123,Dave,25,US
I have an array of database objects and I'm using foreach() to present the names and projects. Good, now the customer doesn't want duplicate names for when one person has multiple projects. This has to do with variable scope and this is my failed attempt to pull this stunt off. Here's a partial var_dump of the array of objects.
array [
0 => {
["lastName"]=>
string(1) "w"
["projectName"]=>
string(29) "Bone density scanner analysis"
}
1 => {
["lastName"]=>
string(1) "w"
["projectName"]=>
string(29) "analysis of foot"
}
]
What I want to end up with is:
array [
0 => {
["lastName"]=>
string(1) "w"
["projectName"]=>
string(29) "Bone density scanner analysis"
}
1 => {
["lastName"]=>
string(1) ""
["projectName"]=>
string(16) "analysis of foot"
}
]
Here's what I was thinking that doesn't seem to work:
function suppress_name($name){
global $string;
return ($name == $string) ? '' : $string;
}
function overall() {
//$result = database call to get objects
foreach ($result as $item) {
$string = $item->lastName;
$rows = array('Name' => suppress_name($item->lastName), 'project' => $item->projectName);
}
}
Researching I see several references to array_unique() which I use for a flattened array, but I can't see that it would help me here. OK, I thought I could make a function, like the above, to handle duplicates and use the $global but think I'm not grasping how to use globals in this instance. I'm happy to be pointed to a better way, or better search terms. Does this make sense?
Here is a possible approach to your solution, where we store the last names in a one dimensional array then check against it through each iteration of the array. If the lastName is in the array then set the value to ''.
Note the use of the reference (&).
<?php
$arrays = array(
array('lastName' => 'w', 'projectName' => 'Bone density scanner analysis'),
array('lastName' => 'w', 'projectName' => 'analysis of foot')
);
$last_names = array();
foreach($arrays as &$array){
if( in_array($array['lastName'],$last_names) ){
$array['lastName'] = '';
}else{
$last_names[] = $array['lastName'];
}
}
echo '<pre>',print_r($arrays),'</pre>';
It would be easier to work with nested arrays
array [
0 => {
["lastName"]=> string(1) "w"
["projects"]=> array [
0 => {
["projectName"] => string(29) "Bone density scanner analysis"
}
1 => {
["projectName"]=> string(16) "analysis of foot"
}
1 => {
["lastName"] => string(1) "x"
["projects"] => array [
0 => {
["projectName"] => string(16) "analysis of head"
} ]
}
]
This question already has answers here:
array_splice() for associative arrays
(14 answers)
Closed 7 years ago.
I've taken a look at this question, but I can't seem to get the code to work for my purposes.
I have an array ($array) structured like so, full of data from a database:
array(369) {
array(3) {
["id"] => string(5) "12345",
["title"] => string(11) "Hello World",
["description"] => string(n) "..."
}
array(3) {
["id"] => string(5) "12346",
["title"] => string(13) "Goodbye World",
["description"] => string(n) "..."
}
...
}
However, this array data will be creating a CSV, and I need to insert empty columns as well. Therefore I need the array to end up looking like this:
array(369) {
array(5) {
["id"] => string(5) "12345",
["title"] => string(11) "Hello World",
["title2"] => string(0) "",
["description"] => string(n) "...",
["description2"] => string(0) ""
}
array(5) {
["id"] => string(5) "12346",
["title"] => string(13) "Goodbye World",
["title2"] => string(0) "",
["description"] => string(n) "...",
["description2"] => string(0) ""
}
...
}
I've tried using array_splice() to enter blank values at the relevant points:
array_splice($array, 2, 0, "");
array_splice($array, 4, 0, "");
But this ends up just breaking the array, and later code utlising fputcsv() doesn't even recognise it as an array. How can I enter these blank values?
foreach ($array as $value) {
fputcsv($fp, $value);
}
Please note: What the array key is labelled as does not matter. It can be as suggested above, blank, numeric, zero... all that's important is that I need a blank value.
$array = array_map(function (array $row) {
static $default = [
'id' => null,
'title' => null,
'title2' => null,
'description' => null,
'description2' => null
];
return array_merge($default, $row);
}, $array);
array_merge keeps the structure (keys and order) of the first array, but replaces any values whose keys match with the second array.