merge and create array from two different sized arrays - php

I need to take two arrays, and combine them to look like this. Not sure how. Here are the two arrays.
$items = array( 'activity', 'photos');
$activity_subitems = array ('var1', 'var2', 'var3');
$photo_subitems = array ('var1', 'var2');
I would like it to be in an array like this;
$query_vars = array(
'activity' => 'var1',
'activity' => 'var2',
'activity' => 'var3',
'photos' => 'var1',
'photos' => 'var2'
);

If the resulting array is a dictionary, you can't, because you are creating more than one same Key for multiple Values. If it is not a dictionary, rephrase the question please.
If what you want is to create something like this:
Array (
[activity] => Array (
[0] => var1
[1] => var2
[2] => var3
)
[photos] => Array (
[0] => var1
[1] => var2
)
)
Then you can do it like this (assuming this is PHP we are talking about):
$items = array( 'activity', 'photos');
$activity_subitems = array ('var1', 'var2', 'var3');
$photos_subitems = array ('var1', 'var2');
$query_vars = array();
foreach ($items as $item) {
$query_vars[$item] = ${$item.'_subitems'};
}
print_r($query_vars);
Also, keep in mind that the value names for the subarrays are generated from the values from the first array by appending _subitems to them.
I have renamed the variable $photo_subitems to $photos_subitems for this to work, because that is the value from the $items array.

I don't recognize the language, but in a pseudo-code kinda way
query_vars = new array();
for ($i in $items) {
for ($j in $i+'_subitems') {
query_vars.add($i, $j);
}
}
keeping in mind that you're creating the variable $j from from the value stored in $items (located # $j) and a static field _items

I am assuming you are working with PHP. First off, you will not be able to have multiple values with the same key in your array, but if you wish, you can make the values keyed to arrays themselves.
$items = array( 'activity', 'photos');
$activity_subitems = array ('var1', 'var2', 'var3');
$photo_subitems = array ('var1', 'var2');
$query_vars = array();
$query_vars['activity'] = $activity_subitems
$query_vars['photo'] = $photo_subitems
If you would like to have an array where the strings themselves start with photo/activity, but where it is not a dictionary (again, can't have duplicate keys), you can do something like the following:
NOTE: the eval() function is generally considered unsafe, and is not recommended for use in just about every language I know, and this is also true for PHP. Use the following at your own risk, but as long as you have strong control over what text can be placed into an eval() call (i.e., no user input is ever used), it should be somewhat safer. I get the impression you might want to use the values in $items to say what variable to use when building your result.
$items = array( 'activity', 'photos');
$activity_subitems = array ('var1', 'var2', 'var3');
$photos_subitems = array ('var1', 'var2');
$query_vars = array();
foreach ($items as &$item) {
foreach (eval('$'.$item.'_subitems') as &$subitem) {
$query_vars[] = $item.' =>'.$subitem;
}
}

Related

create nested array from string with delimiter

I has a string like as brachA-branchB-branchC. I am trying to make it as nested array as follows
[
'name'=>'brachA',
'sub'=> [
'name'=>'brachB',
'sub'=>[
'name'=>'brachC'
]
]
]
I tried as follows (https://3v4l.org/A781D)
<?php
$nested_array = array();
$temp = &$nested_array;
$item = 'brachA-branchB-branchC';
foreach (explode('-', $item) as $key => $value) {
$temp = &$temp[$value];
}
print_r($nested_array);
Output I am getting as follows
Array
(
[brachA] => Array
(
[branchB] => Array
(
[branchC] =>
)
)
)
Any idea, how to achieve this ?
It can probably be done using a foreach loop over the reversed array returned by explode() but it is much easier to use a recursive function.
function makeArray(array $pieces)
{
$first = array_shift($pieces);
$array = array('name' => $first);
if (count($pieces)) {
$array['sub'] = makeArray($pieces);
}
return $array;
}
$item = 'brachA-branchB-branchC';
print_r(makeArray(explode('-', $item)));
The makeArray() function receives an array with the string pieces. It puts the first item under the 'name' key of a new array and invokes itself with the rest of the array to generate the array to put under the 'sub' key. It doesn't put anything for the 'sub' key if there is no rest (on the last call, $pieces is array('brachC').

PHP: Updating an associative array though a class function?

I want to be able to update an associative array within an object based on function input, but I'm at a loss for how to do this. Here's my problem. Let's say there's this data container in my object:
private $vars = Array
(
['user_info'] = Array
(
['name'] => 'John Doe'
['id'] => 46338945
['email'] => 'johndoe#example.com'
['age'] => 35
)
['session_info'] = Array
(
['name'] => 'session_name'
['id'] => 'mGh44Jf0nfNNFmm'
)
)
and I have a public function update to change these values:
public function update($keys, $changeValueTo) {
if (!is_array($keys)) {
$keys = array($keys);
}
nowWhat();
}
Ultimately, I just want to be able to convert something like this
array('user_info', 'name')
into this:
$this->vars['user_info']['name']
so I can set it equal to the $equalTo parameter.
This usually wouldn't be a problem, but in this scenario, I don't know the schema of the $vars array so I can't write a foreach statement based on a fixed number of keys. I also can't just make $vars public, because the function needs to do something within the object every time something is changed.
I'm worried that this is a recursive scenario that will involve resorting to eval(). What would you recommend?
It is not hard to do it. You need passing variable by reference and a loop to achieve. No need eval().
$var = array(
"user_info" => array(
"name" => "Visal"
)
);
function update(&$var, $key, $value) {
// assuming the $key is an array
$t = &$var;
foreach ($key as $v) {
$t = &$t[$v];
}
$t = $value;
}
update($var, array("user_info", "name"), "Hello World");
var_dump($var);

Create an array from the keys of an array

Let's pretend I have this:
$str = "/a/b/c/d/";
$arr = array_filter( explode("/", $str );
At this point $arr contains 4 elements. Is there a way I could create a path in an array with those 4 elements, such as:
$result = [
"a" => [
"b" => [
"c" => [
"d" => [
]
]
]
]
]
...without iterating over $arr?
I know that
$x["a"]["b"]["c"]["d"] = 1;
is perfectly valid and it will create a 4 levels array even if $x wasn't declared as an array, so what I'm asking should be possible.
I DO NOT recommend this as there are security implications when using eval(). However, because I stated in the comments that it couldn't be done without iteration, I felt compelled to post this as an answer (yes, I know implode() iterates internally).
$str = "/a/b/c/d/";
$arr = array_filter( explode("/", $str ));
$keys = '["'.implode('"]["', $arr).'"]';
eval('$x'.$keys.' = 1;');
print_r($x);
For a more practical way see How to write getter/setter to access multi-leveled array by dot separated key names?
I wrote a function once, that had this behaviour as a side effect. It doesn't iterate, but uses recursion.
See: https://github.com/feeela/php-utils/blob/master/function.getArrayValueReference.php
You may call like that:
<?php
$newArray = array();
$keys = 'a/b/c/d';
$referenceToD =& getArrayValueReference( $newArray, explode( '/', $keys ), true );
$referenceToD[0] = 'foo';
$referenceToD[1] = 'bar';
print_r( $newArray );
This modifies the array $newArray and creates all the levels. The functions return value is a reference to the last key ('d' in that example).
…which results in:
Array (
[a] => Array (
[b] => Array (
[c] => Array (
[d] => Array (
[0] => foo
[1] => bar
)
)
)
)
)
There is no way to use all the values of $arr without iterating over it.
I guess you don't want to write a foreach loop but use some PHP function that does the iteration for you.
A simple solution that iterates two times over the array (behind the scene)
This is a possible solution:
$x = array_reduce(
array_reverse($arr),
function ($carry, $item) {
return [$item => $carry];
},
1
);
It generates the same result as:
$x = [];
$x['a']['b']['c']['d'] = 1;
Unfortunately it iterates over $arr two times (array_reverse() and array_reduce()).
Another solution that generates a hierarchy of objects
Another approach that generates the required embedding using objects (stdClass) instead of arrays:
$out = new stdClass;
array_reduce(
$arr,
function ($carry, $item) {
$v = new stdClass;
$carry->{$item} = $v;
return $v;
},
$out
);
It works using a single iteration over $arr but it relies on the way the objects are handled in PHP to work (and this doesn't work with arrays).
PHP handles the objects in a way that makes them look like they are passed by reference. It's a common misconception that the objects are "passed by reference" in PHP but this is not true. A double indirection is responsible for this behaviour.
A recursive solution
function makeArray(array $arr, $initial)
{
if (! count($arr)) {
return $initial;
} else {
$key = array_shift($arr);
return [ $key => makeArray($arr, $initial) ];
}
}
$out = makeArray($arr, 1);
This solution iterates only once over the array and generates a hierarchy of arrays but recursivity is disastrous for large input arrays because it uses a lot of memory.

How to randomly loop through first layer of nested associative array in PHP?

I have a nested assocative array which might look something like this:
$myarray = array(
['tiger'] => array(
['people'], ['apes'], ['birds']
),
['eagle'] => array(
['rodents'] => array(['mice'], ['squirrel'])
),
['shark'] => ['seals']
);
How can I loop through the first layer (tiger, eagle, shark) in a random order and ensure that I cover them all in my loop? I was looking at the PHP function shuffle();, but I think that function messes up the whole array by shuffling all layers.
You can randomly sort an array like this, it will keep the keys and the values
<?php
$myarray = array(
'tiger' => array(
'people', 'apes', 'birds'
),
'eagle' => array(
'rodents' => array('mice', 'squirrel')
),
'shark' => 'seals'
);
$shuffleKeys = array_keys($myarray);
shuffle($shuffleKeys);
$newArray = array();
foreach($shuffleKeys as $key) {
$newArray[$key] = $myarray[$key];
}
print_r($newArray);
You can get the keys using array_keys(). Then you can shuffle the resulting key array using shuffle() and iterate through it.
Example:
$keys = array_keys($myarray);
shuffle($keys);
foreach ($keys as $key) {
var_dump($myarray[$key]);
}
According to my test, shuffle only randomizes 1 layer. try it yourself:
<?php
$test = array(
array(1,2,3,4,5),
array('a','b','c','d','e'),
array('one','two','three','four','five')
);
shuffle($test);
var_dump($test);
?>

PHP How to push array into array[key]?

This is the code I have:
$orders = Array();
foreach ($unassigned as $uorder) {
$array = Array(
"ordid" => $uorder->idord,
"fecha" => $uorder->datorod,
"cliente" => $uorder->idcli
);
array_push($orders[$uorder->user_id], $array);
}
print_r($orders);
Which results:
Array (
[vendor1] =>
[vendor2] =>
)
I want to make some kind of sort
So I could use $orders[vendor1][0][ordid] to find the first order that the vendor made.
You have to assign $orders[$uorder->user_id] as an array first, otherwise it doesn't make sense to push an item onto it. Additionally, you can use the shorthand append notation:
if(!isset($orders[$uorder->user_id]))
$orders[$uorder->user_id] = array();
$orders[$uorder->user_id][] = $array;
In your foreach loop check if $orders[$uorder->user_id] is an array, if not create one.
foreach($unassigned as $uorder):
if(! is_array($orders[$uorder->user_id]))
$orders[$uorder->user_id] = array();
array_push($orders[$uorder->user_id],Array("ordid" => $uorder->idord, "fecha" => $uorder->datorod, "cliente" => $uorder->idcli));
endforeach;

Categories