This question already has answers here:
Get key of multidimensional array?
(5 answers)
Using a string path to set nested array data [duplicate]
(8 answers)
Closed 5 years ago.
I'm writing a PHP script in which I got a multidimensional array without fixed depth. Eg:
$myArray = [
'item01' => [
'section01' => [
'part01'
]
],
'item02' => [
'section02' => [
'part02' => [
'something01'
]
]
],
'item03' => [
'section03'
]
]
I have a string that contains the path to the value that should be changed. Eg:
$myPath = 'item02/section02/part02'
And I have the new value:
$myValue = 'somethingElse'
What I'm trying to do, is go through array $myArray following the path set in $myPath to change the value to $myValue.
The expected output, with the examples above, would be this:
$myArray = [
'item01' => [
'section01' => [
'part01'
]
],
'item02' => [
'section02' => [
'part02' => [
'somethingElse'
]
]
],
'item03' => [
'section03'
]
]
I've tried several ways, but keep getting stumped on this. In the end, it always reaches a point where the solution is, at its core, the same. Rubber duckying didn't help either. Other programmers I know, haven't been able to find a solution either.
I'm hoping someone here can at least provide some fresh ways to look into this.
PS: Everything above is in pseudo-code, as this problem doesn't seem to be language-specific.
try the following:
$myPath = 'item02/section02/part02';
$path = explode('/', $myPath);
$arr = &$myArray;
foreach($path as $key)
{
$arr = &$arr[$key];
}
$arr = "somethingElse";
var_dump($myArray);
First turn the $myPath string into an array of keys using explode.
This uses a simple loop foreach loop to loop over the array using keys, and then by passing the values by reference it replaces the deepest value. Demo Here
Related
This question already has an answer here:
Get key from first array on Search Array in Array PHP
(1 answer)
Closed 3 months ago.
I'm using PHP 7.4. I have this array :
$sections = [
'sectionOne' => [
'foo',
'bar',
'hello',
],
'sectionTwo' => [
'yo',
'heya',
],
];
I'd like to build a function to return the section of the received array value
public function getSectionByValue($value) {
return ...
}
If the value is bar then I'll get sectionOne. If the value is yo then I'll get sectionTwo etc...
How can I do to search an array value inside an array ? It is possible to do this in one line ?
You can do something like this inside getSectionByValue function if you really want an one liner.
return key(array_filter($sections, fn($section) => in_array($value, $section)));
If the provided value exists in multiple sections, it will just return the first one.
This question already has answers here:
Is there a function to extract a 'column' from an array in PHP?
(15 answers)
Closed 9 months ago.
I have this array. I want to get the array values to a same array,how can I achieve that?
Array
(
[0] => Array
(
[referrer_id] => usr157
)
[1] => Array
(
[referrer_id] => usr42
)
)
I want this array to be
array("usr157", "usr42")
use array_walk_recursive to achieve the result as follows
<?php
$main = [];
$ref =
[
[
"referrer_id" => "usr157"
],
[
"referrer_id" => "usr42"
]
];
array_walk_recursive($ref, function ($item, $key) use(&$main) {
$main[] = $item;
} );
print_r($main);
You can check that out here
You can just access the array components like this:
// The next line just recreates your example array into a variable called $x:
$x = array(array('referrer_id' => 'usr157'), array('referrer_id' => 'usr42'));
$result = array($x[0]['referrer_id'], $x[1]['referrer_id']);
print_r($result); //print the result for correctness checking
$result will be the output array you wanted.
Using $x[0], you refer the first element of your input array (and hence, $x[1] the second one, ...). Adding ['referrer_id'] will access its referrer_id key. The surrounding array(...) puts the values into an own array.
You can "automate" the whole thing in case you have a bigger input array using a loop.
You may use array_column to achieve that
$flatten = array_column($array, 'referrer_id');
You can also use array_map and array_values together.
$array = [
[
"referrer_id" => "usr157"
],
[
"referrer_id" => "usr42"
]
];
$flatten = array_map(function($item) {
return array_values($item)[0];
}, $array);
var_dump($flatten);
Also you can use the one-liner if you're using latest version of php that support arrow function
$flatten = array_map(fn($item) => array_values($item)[0], $array);
Or without array_values, you may specify the key
$flatten = array_map(fn($item) => $item['referrer_id'], $array);
You can see the demo here
This question already has answers here:
Transposing multidimensional arrays in PHP
(12 answers)
Closed 6 months ago.
I'm not sure how to search for the problem I'm facing, so that's why I'm asking here.
I want to know if there is a native php-function to transform following array I get from a html-form:
Original Array
$array = [
'product_template_id' => [
'0' => '1',
'1' => '2'
],
'amount' => [
'0' => '50',
'1' => '100'
]
]
Desired Array
$array = [
'0' => [
'product_template_id' => '1',
'amount' => '50'
],
'1' => [
'product_template_id' => '2',
'amount' => '100'
]
]
I know this can be done with a loop, but that's not what I'm asking for.
PS(not my main question, just a sidequestion): How can I bulk format code in stackoverflow? Is it always 4 spaces? How can I perform the formatting quicker?
edit: PS is not the main question, it is more of a sidenote which has already been answered by #RiggsFolly
Just as prove of concept you can use array_map:
$keys = array_keys($array);
// For < PHPv5.6
// $zip = call_user_func_array('array_map', array_merge([null], $array));
$zip = array_map(null, ...array_values($array));
$result = array_map(function ($item) use ($keys) {
return array_combine($keys, $item);
}, $zip);
Here is working demo.
But in practice, there is too much overhead for so simple problem.
EDIT:
Here I am zipping (getting one corresponding element from each array and creating an array of this elements) all child arrays. It is done with array_map using its property:
An interesting use of this function is to construct an array of arrays, which can be easily performed by using NULL as the name of the callback function
As array_map can take an arbitrary number of arrays, I supply them to it with '...' splat operator.
This does what you need!
for ($x = 0; $x < count($array['amount']); $x ++) {
$arr[$x] = [
'product_template_id' => $array['product_template_id'][$x],
'amount' => $array['amount'][$x],
];
}
See here for a working example https://3v4l.org/dokHK
I'm using RIPS PHP scanner. In one of the php files it has a line as bellow:
$F_XSS = array('echo' => array(array(0), $F_SECURING_XSS), ......)
what is the meaning of "array(array(0)" above?
That mean that the array 'echo' will have a value an array with a value (int) 0
PHP
[
'echo' =>
[
[
0
],
$F_SECURING_XSS
],
....
]
I realize there are a number of questions about multidimensional arrays and foreach loops, and I have spent hours reading through them and trying to get my own loop to work -- without success. If the solution is a duplicate, I'll remove my question (or link to another if that is preferred).
Now, the challenge:
Using an array of returned MYSQL results. The results are from multiple joined tables in an associative array. Now I need to convert it to the multidimensional array I need.
I've got most of it working, but my issue is looping through and adding new items to the right place in the array.
Here's some code:
//example of how array is setup in the way I want, this part works.
foreach($results as $i => $a):
//some other code is here, see below.
$items[$i] = [
"id" => $a['id'],
"itemid" => $a['itemid'],
"name" => $a['name'],
"def" => $a['def'],
"class" => $a['class'],
"timeline" => $a['timeline'],
"files" => [
[0] => [
"id" => $a['fileid'],
"name" => $a['filename'],
"path" => $a['filepath'],
"type" => $a['filetype']
]
],
"tags" => [
[0] => [
"id" => $a['tagid'],
"name" => $a['tagname']
]
]
];
endforeach;
Then I've tried a number of ways to loop through in order to only add to the 'tags' or 'files' if the item 'id' is the same as the last. Here is the current code in my editor, not working:
//inside foreach loop, before above code
if($items[$i-1]['id'] == $a['id']):
//it is the same item, works to here.
if(in_array($a['filename'], $items[$i-1], FALSE)):
//add to files array for last item
$items[$i-1]['files'][] = [
"id" => $a['fileid'],
"name" => $a['filename'],
"path" => $a['filepath'],
"type" => $a['filetype']
];
elseif(in_array($a['tagname'], $items[$i-1], FALSE)):
//add to tags array for last item
$items[$i-1]['tags'][] = [
"id" => $a['tagid'],
"name" => $a['tagname']
];
endif;
else:// else it does the code above
As you can see, my most recent attempt was to use in_array, which I now realize doesn't work on multidimensional arrays. My issue is that I can't figure out how to determine if its a new file or new tag for the same item.
Ultimately, I want an array of 'items' which have multiple 'files' and 'tags.' I'm going to json_encode and use it with JS afterwards.
Any advice on how to get this working or optimize it, would be greatly appreciated.
P.S. As I mentioned above, I know this question has been asked before -- though I wasn't able to get their solutions working for me. I'll remove this question if the solution is a duplicate (as in, it's not really helpful to others). Thank you for any help, it is greatly appreciated!
Don't use "autoincrementing" array indices as they easily get messed up. Use your database id since it's already there:
//example of how array is setup in the way I want, this part works.
foreach($results as $i => $a):
$items[$a['id']] = [ // THIS CHANGED.
"id" => $a['id'],
"itemid" => $a['itemid'],
...
Now, with any further result, you can easily check, if the id is already in your array:
if (isset($items[$a['id']])) {
// We had this id before, just add files/tags to it.
// Check first, if files subarray exists, if not: create it.
if (!isset($items[$a['id']]['files'])) {
$items[$a['id']]['files'] = array();
}
$items[$a['id']]['files'][] = array(...); // add the new file.
// Repeat for tags.
}
If your result could return the same file more than once for an id, you can check if the filename is already in there by using a search function:
$filename = $a['filename'];
if (!searchFilename($filename, $items[$a['id']]['files']) {
// Filename is not in there, yet.
// Add file info.
}
function searchFilename($id, $array) {
foreach ($array as $key => $val) {
if ($val['filename'] === $id) {
return true;
}
}
return false;
}
Same applies to tags in a similar way.
In the end, if you do not want the ids for index of $items, just call:
$items = array_values($items);