Make one array into the keys of a different multi-dimensional array - php

I want to take aa array like this [2022, 'January', 1] and use it as keys in order to populate the value of a different array, via a function. This is a very simplistic (recognisable) example using dates, but it might not be dates, it could be ['vehicles', 'cars', 'color', 'red']:
public function addToDate($keys, $value){
$this->allCalendarDates.$keys = $value;
}
addToDate([2022, 'January', 1], 'Happy New Year');
The . in the function is definitely not the way to do it, but it kind of illustrates what I need to do. I need it to be:
$this->allCalendarDates[2022]['January'][1] = $value;

You can use list() to extract the values and reorganize as keys.
public function addToDate($keys, $value) {
list($year, $month, $day) = $keys;
$this->allCalendarDates[$year][$month][$day] = $value;
}
addToDate([2022, 'January', 1], 'Happy New Year');
Update
As you changed your requirement to a variable number of arguments you can go with references like this:
public function addToDate($keys, $value) {
$data = [];
$current = &$data;
foreach($keys as $key) {
$current[$key] = [];
$current = &$current[$key];
}
$current = $value;
$this->allCalendarDates[] = $data;
}
addToDate(['vehicles', 'cars', 'color', 'red'], 'Happy New Year');

Related

Using PHP to loop JSON and generate a new format of nested JSON

In PHP, how do I loop through the following JSON Object's date key, if the date value are the same then merge the time:
[
{
date: "27-06-2017",
time: "1430"
},
{
date: "27-06-2017",
time: "1500"
},
{
date: "28-06-2017",
time: "0930"
},
{
date: "28-06-2017",
time: "0915"
}
]
Result should looks like this:
[
{
date: "27-06-2017",
time: [{"1430","1500"}]
}, {
date: "28-06-2017",
time: [{"0930, 0915"}]
}
]
Should I create an empty array, then the looping through the JSON and recreate a new JSON? Is there any better way or any solution to reference?
Thank you!
This solution is a little overhead, but if you are sure that your data is sequential and sorted, you can use array_count_values and array_map:
$count = array_count_values(array_column($array, 'date'));
$times = array_column($array, 'time');
$grouped = array_map(function ($date, $count) use (&$times) {
return [
'date' => $date,
'time' => array_splice($times, 0, $count)
];
}, array_keys($count), $count);
Here is working demo.
Another Idea to do this is
<?php
$string = '[{"date": "27-06-2017","time": "1430"},{"date": "27-06-2017","time": "1500"},{"date": "28-06-2017","time": "0930"},{"date": "28-06-2017","time": "0915"}]';
$arrs = json_decode($string);
$main = array();
$temp = array();
foreach($arrs as $arr){
if(in_array($arr->date,$temp)){
$main[$arr->date]['time'][] = $arr->time;
}else{
$main[$arr->date]['date'] = $arr->date;
$main[$arr->date]['time'][] = $arr->time;
$temp[] = $arr->date;
}
}
echo json_encode($main);
?>
live demo : https://eval.in/787695
Please try this:
$a = [] // Your input array
$op= [];//output array
foreach($a as $key => $val){
$key = $val['date'];
$op[$key][] = $val['time'];
}
$op2 = [];
foreach($op as $key => $val){
$op2[] = ['date' => $key, 'time' => $val];
}
// create the "final" array
$final = [];
// loop the JSON (assigned to $l)
foreach($l as $o) {
// assign $final[{date}] = to be a new object if it doesn't already exist
if(empty($final[$o->date])) {
$final[$o->date] = (object) ['date' => $o->date, 'time' => [$o->time]];
}
// ... otherwise, if it does exist, just append this time to the array
else {
$final[$o->date]->time[] = $o->time;
}
}
// to get you back to a zero-indexed array
$final = array_values($final);
The "final" array is created with date based indexes initially so that you can determine whether they've been set or not to allow you to manipulate the correct "time" arrays.
They're just removed at the end by dropping $final into array_values() to get the zero-indexed array you're after.
json_encode($final) will give you want you want as a JSON:
[{"date":"27-06-2017","time":["1430","1500"]},{"date":"28-06-2017","time":["0930","0915"]}]
Yet another solution :
$d = [];
$dizi = array_map(function ($value) use (&$d) {
if (array_key_exists($value->date, $d)) {
array_push($d[$value->date]['time'], $value->time);
} else {
$d[$value->date] = [
'date' => $value->date,
'time' => [$value->time]
];
}
}, $array);
echo json_encode(array_values($d));

how to add key name to array?

$arr_type=array(
"1"=>"A",
"2"=>"B",
"3"=>"C",
"4"=>"D",
"5"=>"E",
"6"=>"F",
"7"=>"G",
"8"=>"H"
);
how to change key name and level change?
$arr_type['1']['name'] = A;
$arr_type['2']['name'] = B;
$new_arr = array();
foreach($arr_type as $k => $v){
$new_arr[$k]['name'] = $v;
}
Since this got chosen, I'm also adding #Mark Baker's comment using array_walk here:
array_walk($arr_type, function (&$value) { $value = ['name' => $value]; });
In case one wants to keep the original array unchanged, this solution would also work:
$result = array_map(function ($value) { return ['name' => $value]; }, $arr_type);

Merge objects in PHP

I have for example:
$onePack = $pack->findByCity('London'); //this return me 3 objects from class Pack
$twoPack = $pack->findByCity('New York'); //this return me 2 objects from class Pack
$threePack = $pack->findByCity('Los Angeles'); //this return me 5 objects from class Pack
And I would like merge this object to one variable and next use with foreach.
I know - i can make array, for example:
$array = array();
and next:
foreach($onePack as $one) {
$array[] = $one;
}
foreach($twoPack as $two) {
$array[] = $two;
}
foreach($threePack as $three) {
$array[] = $three;
}
And now I have all objects (10) in one variable, but maybe is better way for this?
How about:
$cities = array('London', 'New York', 'Los Angeles');
$arr = array();
foreach($cities as $city) {
$arr[] = $pack->findByCity($city);
}
You can add new cities to the cities array and they will all be added to the $arr variable
You can use array_merge
$arr = array_merge($pack1->toArray(), $pack2->toArray(), $pack3->toArray());
And create an toArray method in the pack object.

How to reference cells with specific condition in php multidimensional array

I got an array like this:
$array[0][name] = "Axel";
$array[0][car] = "Pratzner";
$array[0][color] = "black";
$array[1][name] = "John";
$array[1][car] = "BMW";
$array[1][color] = "black";
$array[2][name] = "Peggy";
$array[2][car] = "VW";
$array[2][color] = "white";
I would like to do something like "get all names WHERE car = bmw AND color = white"
Could anyone give advice on how the PHP spell would look like?
function getWhiteBMWs($array) {
$result = array();
foreach ($array as $entry) {
if ($entry['car'] == 'bmw' && $entry['color'] == 'white')
$result[] = $entry;
}
return $result;
}
Edited: This is a more general solution:
// Filter an array using the given filter array
function multiFilter($array, $filters) {
$result = $array;
// Removes entries that don't pass the filter
$fn = function($entry, $index, $filter) {
$key = $filter['key'];
$value = $filter['value'];
$result = &$filter['array'];
if ($entry[$key] != $value)
unset($result[$index]);
};
foreach ($filters as $key => $value) {
// Pack the filter data to be passed into array_walk
$filter = array('key' => $key, 'value' => $value, 'array' => &$result);
// For every entry, run the function $fn and pass in the filter data
array_walk($result, $fn, $filter);
}
return array_values($result);
}
// Build a filter array - an entry passes this filter if every
// key in this array corresponds to the same value in the entry.
$filter = array('car' => 'BMW', 'color' => 'white');
// multiFilter searches $array, returning a result array that contains
// only the entries that pass the filter. In this case, only entries
// where $entry['car'] = 'BMW' AND $entry['color'] = 'white' will be
// returned.
$whiteBMWs = multiFilter($array, $filter);
Doing this in code is more or less emulating what a RDBMS is perfect for. Something like this would work:
function getNamesByCarAndColor($array,$color,$car) {
$matches = array();
foreach ($array as $entry) {
if($entry["color"]== $color && $entry["car"]==$car)
matches[] = $entry["name"];
}
return $matches;
}
This code would work well for smaller arrays, but as they got larger and larger it would be obvious that this isn't a great solution and an indexed solution would be much cleaner.

Merge array items into string

How do I merge all the array items into a single string?
Use the implode function.
For example:
$fruits = array('apples', 'pears', 'bananas');
echo implode(',', $fruits);
Try this from the PHP manual (implode):
<?php
$array = array('lastname', 'email', 'phone');
$comma_separated = implode(",", $array);
echo $comma_separated; // lastname, email, and phone
// Empty string when using an empty array:
var_dump(implode('hello', array())); // string(0) ""
?>
If you are trying to just concatenate all of strings in the array, then you should look at implode().
$array1 = array(
"one",
"two",
)
$array2 = array(
"three",
"four",
)
$finalarr = array_merge($array1, $array2);
$finalarr = implode(",", $finalarr);
will produce this one,two,three,four
You can use join. It's an alias for implode, and in my opinion more readable:
$fruits = array('apples', 'pears', 'bananas');
echo join(',', $fruits);
join(" -- ", Array("a", "b")) == "a -- b"
actually join is an alias for the implode function.
If you want to merge the string representation of a group of objects into a single string, you can use implode on an array of those objects. The objects' classes just have to have the __toString() magic method defined.
class myClass {
protected $name;
protected $value;
public function __construct($name,$value) {
$this->name = $name;
$this->value = $value;
}
public function __toString() {
return $this->name . '/' . $this->value;
}
}
$obj1 = new myClass('one',1);
$obj2 = new myClass('two',2);
$obj_array = array($obj1, $obj2);
$string_of_all_objects = implode('|',$obj_array);
echo $string_of_all_objects; // 'one/1|two/2'
I found that trick useful to quickly get a string representation of a group of objects for display on a webpage. No need to loop through the object array with foreach and using echo $obj->get('name').
EDIT: And here's and example with a "collection" class. I have 2 outputs (echos) at the end. The 2nd one should work, but I'm not sure about the 1st.
class myCollectionClass implements IteratorAggregate {
protected $objects = array();
public function __construct() {};
public function add(myClass $object) {
$this->objects[] = $object;
return $this; // fluid
}
public function getIterator() { // for the interface
return new ArrayIterator($this->objects);
}
public function __toString() {
return implode($this->objects);
}
}
$my_collection = new myCollectionClass();
$my_collection->add($obj1)->add($obj2); // add both myClass objects to the collection. can do in one line because fluid
//echo implode('|',$my_collection); // Comment out myCollectionClass's __toString method to test this. does it work? I'm not sure. But the next line will work thanks to myCollectionClass' __toString, which itself uses myClass's __toString
echo $my_collection; // same output as previous block before EDIT.
$array= array( "Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang" );
$string="";
foreach ( $tempas $array) {
$string=$string.",".$temp;
}
foreach($array as $key => $value) {
$string .= $value .' ';
}
For Multi Array such as:
$multi_arrays = array(
0 => array('model' => 'Product 1'),
1 => array('model' => 'Product 2'),
2 => array('model' => 'Product 3'),
3 => array('model' => 'Product 4'));
$pattern = array('/\[/', '/\]/', '/{"model":/', '/}/', '/\"/');
$str_models = preg_replace($pattern, '', json_encode( $multi_arrays));
The result will be:
Product 1, Product 2, Product 3, Product 4
You can change pattern for get any result you want!

Categories