Hi I am working on very complex array operations.
I have $temp variable which stores pipe separated string like Height=10|Width=20
I have used explode function to convert into array and get specific output.
Below code i have try :
$product_attributes = explode("|",$temp)
//below output i get after the explode.
$product_attributes
Array(
[0]=>Height=10
[1]=>width=20
)
But i want to parse this array to separate one.
My expected output :
Array (
[0]=>Array(
[0] => Height
[1] => 10
)
[1]=>Array(
[0]=>Width
[1]=>20
)
)
Which function i need to used to get the desire output ?
Before downvoting let me know if i have made any mistake
You could try the below code. I've tested this and it outputs the result you've shown in your post.
$temp = 'Height=10|Width=20';
$product_attributes = explode('|', $temp);
$product_attributes2 = array();
foreach ($product_attributes as $attribute) {
$product_attributes2[] = explode('=', $attribute);
}
print_r($product_attributes2);
Try Below code
<?php
$temp = "Height=10|Width=20";
$product_attributes = explode("|", $temp);
foreach ($product_attributes as $k => $v) {
$product_attributes[$k] = explode('=', $v);
}
echo '<pre>';
print_r($product_attributes);
?>
check running answer here
Process your result by this:
$f = function($value) { return explode('=', $value); }
$result = array_map($f, $product_attributes);
One more option is to split the values in to one array and then build them from there.
$str = "Height=10|Width=20";
$arr = preg_split("/\||=/", $str);
$arr2= array();
$j=0;
for($i=0;$i<count($arr);$i++){
$arr2[$j][]= $arr[$i];
$arr2[$j][]= $arr[$i+1];
$i++;
$j++;
}
var_dump($arr2);
The output will be:
$arr = array(4){
0 => Height
1 => 10
2 => Width
3 => 20
}
$arr2 = array(2) {
[0]=>
array(2) {
[0]=>
string(6) "Height"
[1]=>
string(2) "10"
}
[1]=>
array(2) {
[0]=>
string(5) "Width"
[1]=>
string(2) "20"
}
}
Related
I have an array say,
$arr = ["x", "y", "z"];
What I want to achieve is create another array based on given array such as
$arr1["x" =>["y" => ["z"]]] = "some value";
Any idea to achieve this? Thanks in advance.
Edited:
'some value' is just a dummy data. What I'm trying to achieve is the multidimensional structure.
You can recursively build an array, taking and removing the first element of an array on each call :
function buildArray($arr, $someValue)
{
if (count($arr) == 0)
return $someValue;
// the key is the first element of the array,
// removed and returned at the same time using array_shift()
return [ array_shift($arr) => buildArray($arr, $someValue) ];
}
$arr = ["x", "y", "z"];
$arr1 = buildArray($arr, "some value");
var_dump($arr1);
echo "------------------------" . PHP_EOL;
// note that $arr is preserved
var_dump($arr);
This outputs :
array(1) {
["x"]=>
array(1) {
["y"]=>
array(1) {
["z"]=>
string(10) "some value"
}
}
}
------------------------
array(3) {
[0]=>
string(1) "x"
[1]=>
string(1) "y"
[2]=>
string(1) "z"
}
$keys = array('key1', 'key2', 'key3');
$value = 'some value';
$md = array();
$md[$keys[count($keys)-1]] = $value;
for($i=count($keys)-2; $i>-1; $i--)
{
$md[$keys[$i]] = $md;
unset($md[$keys[$i+1]]);
}
print_r($md);
You need to create recursive function:
function rec_arr($ar, $val){
$res = [];
if(is_array($ar) && count($ar)>0){
$tmp = $ar[0]; // catching the first value
unset($ar[0]); // unset first value from given array
sort($ar); // makes indexes as 0,1,...
$res[$tmp] = rec_arr($ar, $val); // recursion
} else {
return $val; // passing value to the last element
}
return $res;
}
Demo
Outputs:
Array
(
[x] => Array
(
[y] => Array
(
[z] => some value
)
)
)
$variable = '
persons.0.name = "peter"
persons.0.lastname = "griffin"
persons.1.name = "homer"
persons.1.lastname = "simpsons"';
I want to generate from that $variable an array that looks like this
array(2) {
[0]=>
array(2) {
["name"]=>
string(5) "peter"
["lastname"]=>
string(7) "griffin"
}
[1]=>
array(2) {
["name"]=>
string(5) "homer"
["lastname"]=>
string(7) "simpson"
}
}
so far this is what I have so far.
$temp = explode('\r\n', $persons);
$sets = [];
foreach ($temp as $value)
{
$array = explode('=', $value);
if ($array[0] != '')
{
$array[1] = trim($array[1], '"');
$sets[$array[0]] = $array[1];
$output = $sets;
}
}
that generates "persons.1.name" as a key and "peter" as a value
I´m not sure how to generate arrays based on "." thank you.
I tried with parse_ini_string() but basically is doing the same thing.
You can use array_reduce and explode
$variable = '
persons.0.name = "peter"
persons.0.lastname = "griffin"
persons.1.name = "homer"
persons.1.lastname = "simpsons"';
$temp = explode(PHP_EOL, $variable);
$result = array_reduce($temp, function($c, $v){
$v = explode( "=", $v );
if ( trim( $v[0] ) !== "" ) {
$k = explode( ".", $v[0] );
$c[ $k[ 1 ] ][ $k[ 2 ] ] = $v[1];
}
return $c;
}, array());
echo "<pre>";
print_r( $result );
echo "</pre>";
This will result to:
Array
(
[0] => Array
(
[name ] => "peter"
[lastname ] => "griffin"
)
[1] => Array
(
[name ] => "homer"
[lastname ] => "simpsons"
)
)
Doc: http://php.net/manual/en/function.array-reduce.php
UPDATE: If you want to set depth, you can
$variable = '
persons.0.name = "peter"
persons.0.lastname = "griffin"
persons.1.name = "homer"
persons.1.lastname = "simpsons"
data = "foo"
url = so.com?var=true
';
$temp = explode(PHP_EOL, $variable);
$result = array_reduce($temp, function($c, $v){
$v = explode( "=", $v, 2 );
if ( trim( $v[0] ) !== "" ) {
$k = explode( ".", $v[0] );
$data = $v[1];
foreach (array_reverse($k) as $key) {
$data = array( trim( $key ) => $data);
}
$c = array_replace_recursive( $c, $data );
}
return $c;
}, array());
echo "<pre>";
print_r( $result );
echo "</pre>";
This will result to:
Array
(
[persons] => Array
(
[0] => Array
(
[name] => "peter"
[lastname] => "griffin"
)
[1] => Array
(
[name] => "homer"
[lastname] => "simpsons"
)
)
[data] => "foo"
[url] => so.com?var=true
)
PHP's ini parsing is limited and wouldn't parse that even if it was persons[0][name] = "peter".
Taken from my answer here How to write getter/setter to access multi-level array by key names?, first just explode on = to get the key path and value, and then explode on . for the keys and build the array:
$lines = explode("\n", $variable); //get lines
list($path, $value) = explode('=', $lines); //get . delimited path to build keys and value
$path = explode('.', $path); //explode path to get individual key names
$array = array();
$temp = &$array;
foreach($path as $key) {
$temp =& $temp[trim($key)];
}
$temp = trim($value, '"');
Also trims spaces and ".
Because each line contains the full address to and data for the array, we can create everything with a loop instead of recursion.
// Create variable for final result
$output=[];
// Loop over input lines, and let PHP figure out the key/val
foreach (parse_ini_string($variable) AS $key=>$val) {
$stack = explode('.', $key);
$pos = &$output;
// Loop through elements of key, create when necessary
foreach ($stack AS $elem) {
if (!isset($pos[$elem]))
$pos[$elem] = [];
$pos = &$pos[$elem];
}
// Whole key stack created, drop in value
$pos = $val;
}
// The final output
var_dump($output);
Output:
array(1) {
["persons"]=>
array(2) {
[0]=>
array(2) {
["name"]=>
string(5) "peter"
["lastname"]=>
string(7) "griffin"
}
[1]=>
array(2) {
["name"]=>
string(5) "homer"
["lastname"]=>
&string(8) "simpsons"
}
}
}
I have a global array in which I am trying to update a value (remain persistent) and then display it.
I get no error but the array never gets updated.
<?php
$anchor = 'bird';
$stuff = array('apple', 'bird', 'frog');
function insert($anchor, $stuff){
foreach($stuff as $part){
$new_array = array($anchor => rand());
if($part == $anchor){
array_push($stuff, $new_array);
}
}
}
for($x = 0; $x < 2; $x++){
insert($anchor, $stuff);
var_dump($stuff);
}
output:
array(3) {
[0]=>
string(5) "apple"
[1]=>
string(4) "bird"
[2]=>
string(4) "frog"
}
array(3) {
[0]=>
string(5) "apple"
[1]=>
string(4) "bird"
[2]=>
string(4) "frog"
}
expected output:
{'bird' => 674568765}
{'bird' => 986266261}
How do I update an array within a function, so that the changes are reflected globally (persistent)?
Pass the variable $stuff by reference. Note the & in the function parameters.
function insert($anchor, &$stuff){ // note the & mark
foreach($stuff as $part){
$new_array = array($anchor => rand());
if($part == $anchor){
array_push($stuff, $new_array);
}
}
}
As others have mentioned: by default, PHP function arguments are passed by value, meaning that a value changed inside a function does not change outside of the function.
I suggest returning the new $stuff value from your function:
<?php
$anchor = 'bird';
$stuff = array('apple', 'bird', 'frog');
function insert($anchor, $stuff){
foreach($stuff as $part){
$new_array = array($anchor => rand());
if($part == $anchor){
array_push($stuff, $new_array);
}
}
return $stuff;
}
for($x = 0; $x < 2; $x++){
$stuff=insert($anchor, $stuff);
}
echo"<pre>".print_r($stuff,true)."</pre>";
?>
Array
(
[0] => apple
[1] => bird
[2] => frog
[3] => Array
(
[bird] => 618490127
)
[4] => Array
(
[bird] => 1869073273
)
)
Other solutions propose passing by reference, to which I'm not opposed. But I have definitely run into buggy code in which it wasn't immediately clear that a function was changing a value, and I've been confused by unexpected loop behavior. As a result, I generally prefer arguably more readable/maintainable code that returns a new value.
See When to pass-by-reference in PHP.
Get technical with Sara Golemon.
If you want changes to a variable that you pass to a function to persist after the function ends, pass the variable by reference:
Change:
function insert($anchor, $stuff)
To
function insert($anchor, &$stuff)
in PHP, is it possible to cut the |xyz part away from the key names?
The array looks like this:
array(30) {
["1970-01-01|802"]=>
array(4) {
["id"]=>
string(3) "176"
["datum"]=>
string(10) "1970-01-01"
["title"]=>
string(8) "Vorschau"
["alias"]=>
string(16) "vorschau-v15-176"
}
["1970-01-01|842"]=>
array(4) {
["id"]=>
string(3) "176"
["datum"]=>
string(10) "1970-01-01"
["title"]=>
string(8) "Vorschau"
["alias"]=>
string(16) "vorschau-v15-176"
} ...
Thank you for your help,
toni
For example, you might use this:
$newArray = array();
foreach( $oldArray as $key => $value ) {
$newArray[ substr( $key, 0, 10 ) ] = $value;
}
Or modify the array in-place:
foreach( $someArray as $key => $value ) {
unset( $someArray[ $key ] );
$someArray[ substr( $key, 0, 10 ) ] = $value;
}
Both solutions will loose value
Since the keys in your source array are
1970-01-01|802
1970-01-01|842
the output array will loose some array values: Both keys get mapped to a single destination key:
1970-01-01
Keeping all values
If you don't want to loose values, try this:
$newArray = array();
foreach( $someArray as $key => $value ) {
$newKey = substr( $key, 0, 10 );
if ( ! isset( $newArray[ $newKey ] )) {
$newArray[ $newKey ] = array();
}
$newArray[ $newKey ][] = $value;
}
Result array structure of this solution:
array(
'1970-01-01' =>
array(
0 => ...,
1 => ...
),
'1970-01-02' =>
array(
0 => ...,
1 => ...,
2 => ...
),
...
);
Kind of.. just create a new array with the trimmed key, then set the old aray equal to the new one.
$newArray = array();
foreach ($arrayList as $key => $data) {
$keyParts = explode("|", $key);
$newArray[$keyParts[0]] = $data;
}
$arrayList = $newArray;
It could be possible but in this case you would end up with 2 of the same array keys.
["1970-01-01"] and ["1970-01-01"]
The xyz behind it is required in this case.
You can do it with preg_replace:
$keys = preg_replace('/(.+)\|\d+/', '$1', array_keys($arr));
$arr = array_combine($keys, $arr);
Just working on something and can't find a simple solution to this problem without just looping through the array with a foreach. Does anyone have a simple solution for this
I want to turn this
&array(4) {
["a"]=>int(0)
["b"]=>int(1)
["c"]=>int(2)
["d"]=>int(3)
}
Into this
array(1) {
["a"]=>
array(1) {
[0]=>
array(1) {
["b"]=>
array(1) {
[0]=>
array(1) {
["c"]=>
array(1) {
[0]=>
array(1) {
["d"]=> int(1) //this value does not matter
}
}
}
}
}
}
}
The values don't matter at all I just need the keys to run against a array_intersect_key_recursive function that I have.
EDIT : The array has changed after testing it needs to be nested as an array of an array
I don't know how this could possibly end up helping you, but it was a fun exercise nonetheless.
$newArray = array();
$last = &$newArray;
$array = array_reverse(array_keys($array));
while ($item = array_pop($array)) {
if (!is_array($last)) {
$last = array();
}
$last[$item] = array(array());
$last = &$last[$item][0];
}
NOTE: I made this answer with the int(1). You said the value is not important so I'm not going to bother changing it for now, but you would have to do a bit more work if the value was important (probably something like get the value from the original array with $item as the key).
Another approach using recursion:
function toNestedArray(array $array, $index = 0) {
$return = array();
if ($index < count($array)) {
$return[$array[$index]] = toNestedArray($array, ++$index);
}
return $return;
}
Usage Example:
$flatArray = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4);
$nestedArray = toNestedArray(array_keys($flatArray));
print_r($nestedArray);
Output:
Array
(
[a] => Array
(
[b] => Array
(
[c] => Array
(
[d] => Array
(
)
)
)
)
)