Merge objects in PHP - 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.

Related

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

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');

How to dynamically traverse a global array without creating any copy of it?

What happen if it is a very big array? One would try to save memory. The next example makes copies of parts of the array, but it should be not necessary, since the array is a global variable.
function arrayTraverse($key) {
global $someArray;
$keys = func_get_args();
$arrayPart = $someArray;
foreach ($keys as $key) {
$arrayPart = $arrayCopy[$key];
}
$value = $arrayPart;
return $value;
}
Usage example:
$someArray = [];
$someArray['aKey'] = [];
$someArray['aKey']['someOtherKey'] = [];
$someArray['aKey']['someOtherKey'][5] = [];
$someArray['aKey']['someOtherKey'][5]['value'] = 'hello';
echo arrayTraverse('aKey', 'someOtherKey', 5, 'value'); // hello

find add or delete values between two array

I write a code for sync two array and know which was must delete and which was add to new array.
<?php
$currentArray = array('ali', 'hasan', 'husein'); //base array read from database
$saveArray = array('husein', 'Hasan', 'taghi'); //requested item for save/delete in database
$deleteArray = array();
$addArray = array();
$currentArray = array_map('strtolower', $currentArray);
$saveArray = array_map('strtolower', $saveArray);
foreach ($currentArray as $a) {
if (!in_array($a, $saveArray))
$deleteArray[] = $a;
}
foreach ($saveArray as $a) {
if (!in_array($a, $currentArray))
$addArray[] = $a;
}
echo 'must be deleted:';
var_dump($deleteArray);
echo 'must be added:';
var_dump($addArray);
?>
Output:
must be deleted:
array
0 => string 'ali' (length=3)
must be added:
array
0 => string 'taghi' (length=5)
Now, Do you thinks is it better, faster and simpler code for this action?
You can use array_udiff() for this, using strcasecmp() as the callback function.
$currentArray = array('ali', 'hasan', 'husein');
$saveArray = array('husein', 'Hasan', 'taghi');
$deleteArray = array_udiff($currentArray, $saveArray, 'strcasecmp');
$addArray = array_udiff($saveArray, $currentArray, 'strcasecmp');
See demo
The values must be the same.
$currentArray = array_map('strtolower', $currentArray);
$saveArray = array_map('strtolower', $saveArray);
And basically use use Array diff.
$deleteArray = array_diff($currentArray, $saveArray);
$addArray = array_diff($saveArray, $currentArray);

PHP Can't get the right format for array

I got stuck somehow on the following problem:
What I want to achieve is to merge the following arrays based on key :
{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}}
{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}}
{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}}
{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}}
{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}}
{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}
Which needs to output like this:
[{"item_header":"Entities"},
{"list_items" :
[{"submenu_id":"Parents","submenu_label":"parents"},
{"submenu_id":"Insurers","submenu_label":"insurers"}]
}]
[{"item_header":"Users"},
{"list_items" :
[{"submenu_id":"New roles","submenu_label":"newrole"}
{"submenu_id":"User - roles","submenu_label":"user_roles"}
{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}]
}]
[{"item_header":"Accounting"},
{"list_items" :
[{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}]
}]
I have been trying all kinds of things for the last two hours, but each attempt returned a different format as the one required and thus failed miserably. Somehow, I couldn't figure it out.
Do you have a construction in mind to get this job done?
I would be very interested to hear your approach on the matter.
Thanks.
$input = array(
'{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}}',
'{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}}',
'{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}}',
'{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}}',
'{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}}',
'{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}',
);
$input = array_map(function ($e) { return json_decode($e, true); }, $input);
$result = array();
$indexMap = array();
foreach ($input as $index => $values) {
foreach ($values as $k => $value) {
$index = isset($indexMap[$k]) ? $indexMap[$k] : $index;
if (!isset($result[$index]['item_header'])) {
$result[$index]['item_header'] = $k;
$indexMap[$k] = $index;
}
$result[$index]['list_items'][] = $value;
}
}
echo json_encode($result);
Here you are!
In this case, first I added all arrays into one array for processing.
I thought they are in same array first, but now I realize they aren't.
Just make an empty $array=[] then and then add them all in $array[]=$a1, $array[]=$a2, etc...
$array = '[{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}},
{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}},
{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}},
{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}},
{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}},
{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}]';
$array = json_decode($array, true);
$intermediate = []; // 1st step
foreach($array as $a)
{
$keys = array_keys($a);
$key = $keys[0]; // say, "Entities" or "Users"
$intermediate[$key] []= $a[$key];
}
$result = []; // 2nd step
foreach($intermediate as $key=>$a)
{
$entry = ["item_header" => $key, "list_items" => [] ];
foreach($a as $item) $entry["list_items"] []= $item;
$result []= $entry;
}
print_r($result);
I would prefer an OO approach for that.
First an object for the list_item:
{"submenu_id":"Parents","submenu_label":"parents"}
Second an object for the item_header:
{"item_header":"Entities", "list_items" : <array of list_item> }
Last an object or an array for all:
{ "Menus: <array of item_header> }
And the according getter/setter etc.
The following code will give you the requisite array over which you can iterate to get the desired output.
$final_array = array();
foreach($array as $value) { //assuming that the original arrays are stored inside another array. You can replace the iterator over the array to an iterator over input from file
$key = /*Extract the key from the string ($value)*/
$existing_array_for_key = $final_array[$key];
if(!array_key_exists ($key , $final_array)) {
$existing_array_for_key = array();
}
$existing_array_for_key[count($existing_array_for_key)+1] = /*Extract value from the String ($value)*/
$final_array[$key] = $existing_array_for_key;
}

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