How to create a nested array out of an array in PHP - php

Say, we have an array: array(1,2,3,4,...)
And I want to convert it to:
array(
1=>array(
2=>array(
3=>array(
4=>array()
)
)
)
)
Can anybody help?
Thanks
EDIT It would be good to have the solution with iterations.

$x = count($array) - 1;
$temp = array();
for($i = $x; $i >= 0; $i--)
{
$temp = array($array[$i] => $temp);
}

You can simply make a recursive function :
<?php
function nestArray($myArray)
{
if (empty($myArray))
{
return array();
}
$firstValue = array_shift($myArray);
return array($firstValue => nestArray($myArray));
}
?>

Well, try something like this:
$in = array(1,2,3,4); // Array with incoming params
$res = array(); // Array where we will write result
$t = &$res; // Link to first level
foreach ($in as $k) { // Walk through source array
if (empty($t[$k])) { // Check if current level has required key
$t[$k] = array(); // If does not, create empty array there
$t = &$t[$k]; // And link to it now. So each time it is link to deepest level.
}
}
unset($t); // Drop link to last (most deep) level
var_dump($res);
die();
Output:
array(1) {
[1]=> array(1) {
[2]=> array(1) {
[3]=> array(1) {
[4]=> array(0) {
}
}
}
}
}

I think the syntax for the multidimensional array you want to create would look like the following.
$array = array(
'array1' => array('value' => 'another_value'),
'array2' => array('something', 'something else'),
'array3' => array('value', 'value')
);
Is this what you're looking for?

You can also use this array library to do that in just one line:
$array = Arr::setNestedElement([], '1.2.3.4', 'value');

Related

Change value within array based on input in php

I am trying to locale the correct sub-array in order to change the count, if a specific value is present more than once.
I have the following code:
$trending = [];
foreach($hashtags as $hashtag) {
if(in_array($hashtag->hashtag, $hashtags))
{
array_search()
}
else {
array_push($trending, [
'hashtag' => $hashtag->hashtag,
'counts' => '1'
]);
}
}
This gives me the following example outout:
array(3) {
[0]=> array(2)
{
["hashtag"]=> "foobar"
["counts"]=> "1"
}
[1]=> array(2)
{
["hashtag"]=> "hashtags"
["counts"]=> "1"
}
[2]=> array(2)
{
["hashtag"]=> "imageattached"
["counts"]=> "1"
}
}
So in the foreach loop and the if statement, i want to check for dublicates of hashtags, e.g. if the hashtag foobar exists more than one time, I don't want to create another dublicate in the array, but I want to change the count to 2
How do I find the correct "sub"-array, and change the count of this to 2, if a hashtag is present within $hashtags more than once??
The idea is, that I at the end can sort these arrays, and get the hashtag that is most common, by looking at the count.
If you change the structure of your output, you could do something like this:
$trending = [];
foreach($hashtags as $tag) {
if (isset($trending[$tag])) $trending[$tag]++;
else $trending[$tag] = 1;
}
Which would result in $trending having the structure
array(2) {
["foobar"] => 1,
["hashtags"] => 2
}
Which could then be looped through with
foreach($trending as $tag => $count) {
echo $tag . ' appears ' . $count . ' times.' . PHP_EOL;
}
The PHP method array_count_values might be of some help.
http://php.net/manual/en/function.array-count-values.php
Have you considered using a keyed array?
$trending = array();
foreach($hashtags as $hashtag) {
if(!isset($trending[$hashtag])){
$trending[$hashtag] = 1;
}else{
$trending[$hashtag] += 1;
}
}
By using a keyed array, there is no duplication and you can easily check how frequently a hashtag is used by just accessing $trending[$hashtag]. Additionally, you can get the list of all hashtags in the trending array using $allHashtags = array_keys($trending);.
Of course, if your project specifications do not allow for this, then by all means, use a different approach, but that would be the approach I would take.
It can be more linear of you can change your array structure but for the current this should work.
$trending = [];
$checker = true;
foreach($hashtags as $hashtag) {
foreach ($trending as $key =>$value) {
if($value["hashtag"] == $hashtag->hashtag){
$trending[$key]["counts"]++;
$checker = false;
}
}
if($checker) {
array_push($trending, [
'hashtag' => $hashtag->hashtag,
'counts' => '1'
]);
}
$checker = true;
}

PHP - Searching in multidimensional array

i'm in a lot of brain-pain, please advise. I have the following situation:
i have the next multidimensional array:
$numbers = array (
"one_digit" => array (1,2,3,4,5),
"two_digits" => array (20,21,22,23,24,25),
"three_digits" => array (301,302,303,304,304),
"mixed_digits" => array (9,29,309,1)
);
i need a way to search in the $numbers array for the following:
-- search if number 20 is in any $numbers array and echo where it is found
ex. $find1 = m_array_search("20", $numbers); echo "i've found the searched value in ".$find1." subarray of $numbers";
result: "i've found the searched value in two_digits subarray of $numbers"
-- search if number 1 is in any $numbers array and echo where it is found
ex. $find2 = m_array_search("1", $numbers); echo "i've found the searched value in ".$find2." subarray of $numbers";
result: "i've found the searched value in two_digits,mixed_digits subarray of $numbers"
thus function must be able to spot presence in one or many "subarrays". sorry if i've missued the term "subarray"
THANK YOU!!!
Simple solution using in_array function:
$search = 1;
$keys = [];
foreach ($numbers as $k => $v) {
if (is_array($v) && in_array($search, $v)) $keys[] = $k;
}
echo "I've found the searched value in ". implode(', ', $keys) ." subarray". ((count($keys) > 1)? "s":"") ." of \$numbers";
The output:
I've found the searched value in one_digit, mixed_digits subarrays of $numbers
Check this and let me know if it helps you .
<?php
function array_find_deep($array, $search, $keys = array())
{
foreach($array as $key => $value) {
if (is_array($value)) {
$sub = array_find_deep($value, $search, array_merge($keys, array($key)));
if (count($sub)) {
return $sub;
}
} elseif ($value === $search) {
return array_merge($keys, array($key));
}
}
return array();
}
$numbers = array (
"one_digit" => array (1,2,3,4,5),
"two_digits" => array (20,21,22,23,24,25),
"three_digits" => array (301,302,303,304,304),
"mixed_digits" => array (9,29,309,1)
);
var_dump(array_find_deep($numbers, 20));
var_dump(array_find_deep($numbers, 1));
var_dump(array_find_deep($numbers, 301));
var_dump(array_find_deep($numbers, 309));
?>
You can store the result in a variable like $result = array_find_deep($numbers, 20); and try echo $result[0] which will give the result that in which array it found the value.
You can try this with array_search() in a loop -
$numbers = array (
"one_digit" => array (1,2,3,4,5),
"two_digits" => array (20,21,22,23,24,25),
"three_digits" => array (301,302,303,304,304),
"mixed_digits" => array (9,29,309,1)
);
function search_value($array, $value)
{
$result = array();
foreach($array as $key => $sub) {
// check if element present in sub array
if(array_search($value, $sub) !== false) {
// store the key
$result[] = $key;
}
}
return $result;
}
var_dump(search_value($numbers, 1));
var_dump(search_value($numbers, 5));
Output
array(2) {
[0]=>
string(9) "one_digit"
[1]=>
string(12) "mixed_digits"
}
array(1) {
[0]=>
string(9) "one_digit"
}

How to create an array based on value in PHP?

I have an array like this
Array
(
[0] => 123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-31).pdf
[1] => 123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-30).pdf
[2] => 123_bms_for__on__(10-06-2015_18-36).pdf
)
I want to convert this into multidimensional array based on its value such
as
Array
(
[dr] => Array
(
[0] => 123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-31).pdf
[1] => 123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-30).pdf
)
[bms] => Array
(
[0] => 123_bms_for__on__(10-06-2015_18-36).pdf
)
)
based on name after first underscore (bms,dr) like....... Please help me to achieve this
I would do the following:
$newArray = array();
foreach ($array as $key => $value) {
$parts = explode('_', $value);
$newArray[$parts[1]][] = $value;
}
print_r($newArray);
To solve this without a loop, it would be smart to use a function along with built in Array Filter function.
Here's another possible solution - which seems a little cooler I suppose;
<?php
// ####################
// GLOBAL VARIABLES DEFINITION
// ####################
// Store Pattern Here = Used to Define Array at the end
global $Array_IDs;
$Array_IDs = array();
// Store Variables With Header Pattern (ID) in this area
global $Array_Values;
$Array_Values = array();
// ####################
// FUNCTION DEFINITION
// ####################
// FUNCTION TO SPLIT ARRAY
function Get_ID($variable){
// ACCESS GLOBALS
global $Array_IDs;
global $Array_Values;
// GET CURRENT VARIBALE - EXPLODE TO EXTRACT PATTERN AS ID
$Temp_Parts = explode("_", $variable);
// CHECK IF IDENTIFIER IS ALREADY FOUND (STORED IN ARRAY_ID)
if (in_array($Temp_Parts[1], $Array_IDs)){
// ID ALREADY HAS SUB-ARRAY CREATED
// JUST APPEND VARIABLE
$Array_Values[$Temp_Parts[1]][] = $variable;
}else{
// ADD ID TO Array_IDs
$Array_IDs[] = $Temp_Parts[1];
// Create New ARRAY with HEADER AS PATTERN - ID
$Array_Values[$Temp_Parts[1]][] = $variable;
}
}
// ####################
// CODE STARTS HERE == ONLY THREE LINES ;)
// ####################
$Start_Array = array('123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-31).pdf','123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-30).pdf','123_bms_for__on__(10-06-2015_18-36).pdf');
array_filter($Start_Array,"Get_ID");
print_r($Array_Values);
?>
Give it a try and let me know how it goes, the output is as requested ;)
You can use array_reduce function and regex matching for elegant & lesser code.
$array = array(
'0'=>'123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-31).pdf',
'1'=>'123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-30).pdf',
'2'=>'123_bms_for__on__(10-06-2015_18-36).pdf'
);
$result = array_reduce($array, function($prod, $current){
preg_match('/(?<=^123_)\w+(?=_for\w+)/',$current,$match);
$prod[$match[0]][] = $current;
return $prod;
}, []);
Will produce the following result.
array(2) {
[0]=>
string(57) "123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-31).pdf"
[1]=>
string(57) "123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-30).pdf"
}
array(1) {
[0]=>
string(39) "123_bms_for__on__(10-06-2015_18-36).pdf"
}
Using square bracket require PHP 5.4 above, you can replace with array() instead for lower version of PHP.
please find below code as per your requirement.
<?php
$array = array(
'0'=>'123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-31).pdf',
'1'=>'123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-30).pdf',
'2'=>'123_bms_for__on__(10-06-2015_18-36).pdf'
);
$dr_array = array();
$bms_array = array();
foreach($array as $val){
$str_explode = explode("_",$val);
if($str_explode[1]=="dr"){
$dr_array[] = $val;
}
else if($str_explode[1]=="bms"){
$bms_array[] = $val;
}
}
var_dump($dr_array);
var_dump($bms_array);
?>
Output :
array(2) {
[0]=>
string(57) "123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-31).pdf"
[1]=>
string(57) "123_dr_for_ma_on_2352015_2nd Shift_(08-29-2015_11-30).pdf"
}
array(1) {
[0]=>
string(39) "123_bms_for__on__(10-06-2015_18-36).pdf"
}
Thanks.
$basicArray = array(); //It Stores All The Elements
$firstArray = array(); //It will store array elements of first type
$secondArray = array(); //It will store array elements of second type
for($i = 0; $i < count($basicArray); $i++)
{
$elementArray = explode("_", $basicArray[i]);
if($elementArray[1] == "dr")
array_push($firstArray, $basicArray[i]);
else if($elementArray[1] == "bms")
array_push($secondArray, $basicArray[i]);
}
$finalArray = array();
array_push($finalArray, $firstArray, $secondArray);

Build multidimensional array from keys

I can't seem to figure this out and I'm hoping someone has a magical recursive solution to this. I have a list of keys and basically I want to transform it into a nested array.
array('level1', 'level2', 'level3');
To
array(
'level1' => array(
'level2' => array(
'level3' // last key in array should be just a value
)
)
)
Much appreciation to anyone who can help!
Something like this should do the job:
function buildMultiDimensional(Array $arr)
{
// the first value will become a new key
$newKey = array_shift($arr);
if (empty($arr)) {
// this is where the recursion stops
return $newKey;
}
// and the recursion !!!
return array($newKey => buildMultiDimensional($arr));
}
$arr = array('level1', 'level2', 'level3', 'level4', 'level5');
var_dump(buildMultiDimensional($arr));
The result is what's expected:
array(1) {
["level1"]=>
array(1) {
["level2"]=>
array(1) {
["level3"]=>
array(1) {
["level4"]=>
string(6) "level5"
}
}
}
}
You don't need recursion. A single loop is fine with references.
<?php
//array to iterate
$array = array('level1', 'level2', 'level3');
//contains our entire array
$out = array();
//temp variable to store references as we go down.
$tmp = &$out;
//get the last value off the array
$last = array_pop($array);
//loop over the array
foreach($array as $level){
//make an array under the current level
$tmp[$level] = array();
//assign tmp to the new level
$tmp = &$tmp[$level];
}
//assign the last key as the value under the last key
$tmp = $last;
//display output
print_r($out);
example: http://codepad.viper-7.com/zATfyo
And without references, working in reverse:
<?php
//array to iterate
$array = array('level1', 'level2', 'level3');
//get the last value off the array
$out = array_pop($array);
//flip the array backwards
$array = array_reverse($array);
//loop over the array
foreach($array as $level){
$out = array($level=>$out);
}
//display output
print_r($out);
Example: http://codepad.viper-7.com/fgxeHO

Recursive strings replacement with PHP

For a project I'm working on, I have a base URI with placeholders and I want to generate all the possible combinations from an array of possible values for each placeholder using PHP.
More concretely:
<?php
$uri = "foo/bar?foo=%foo%&bar=%bar%";
$placeholders = array(
'%foo%' => array('a', 'b'),
'%bar%' => array('c', 'd'),
// ...
);
I'd like ending up having the following array:
array(4) {
[0]=>
string(23) "foo/bar?foo=a&bar=c"
[1]=>
string(23) "foo/bar?foo=a&bar=d"
[2]=>
string(19) "foo/bar?foo=b&bar=c"
[3]=>
string(19) "foo/bar?foo=b&bar=d"
}
Not to mention I should be able to add more placeholders to generate more computed uris, of course, so the solution should work recursively.
I might be overtired these days, but I'm getting stuck at achieving this simply, and I'm sure there's a simple way, perhaps even with builtin PHP functions…
Hints? Any help much appreciated.
<?php
function rec($values,$keys,$index,$str,&$result)
{
if($index<count($values))
foreach($values[$index] as $val)
rec($values,$keys,$index+1,$str.substr($keys[$index],1,strlen($keys[$index])-2)."=".$val."&",$result);
else
$result[count($result)] = $str;
}
// Now for test
$placeholders = array(
'%foo%' => array('a', 'b'),
'%bar%' => array('c', 'd' , 'h'),
);
$xvalues = array_values($placeholders) ;
$xkeys = array_keys($placeholders) ;
$result = array();
rec($xvalues,$xkeys,0,"",$result); // calling the recursive function
print_r($result);
// the result will be:
Array (
[0] => foo=a&bar=c&
[1] => foo=a&bar=d&
[2] => foo=a&bar=h&
[3] => foo=b&bar=c&
[4] => foo=b&bar=d&
[5] => foo=b&bar=h&
)
?>
It handles unlimited count of placeholders & unlimited count of values
$uri= "foo/bar?foo=%foo%&bar=%bar%&baz=%baz%";
$placeholders = array(
'%foo%' => array('a', 'b'),
'%bar%' => array('c', 'd', 'e'),
'%baz%' => array('f', 'g')
);
//adds a level of depth in the combinations for each new array of values
function expandCombinations($combinations, $values)
{
$results = array();
$i=0;
//combine each existing combination with all the new values
foreach($combinations as $combination) {
foreach($values as $value) {
$results[$i] = is_array($combination) ? $combination : array($combination);
$results[$i][] = $value;
$i++;
}
}
return $results;
}
//generate the combinations
$patterns = array();
foreach($placeholders as $pattern => $values)
{
$patterns[] = $pattern;
$combinations = isset($combinations) ? expandCombinations($combinations, $values) : $values;
}
//generate the uris for each combination
foreach($combinations as $combination)
{
echo str_replace($patterns, $combination, $uri),"\n";
}
The idea here is to list in an array all the possible combinations for the replacements. The function expandCombinations just adds one level of depth in the combinations for each new pattern to replace with no recursion (we know how PHP loves recursion). This should allow for a decent number of patterns to replace without recursing at an insane depth.
A recursive solution:
function enumerate($uri, $placeholders){
$insts = array();
if (!empty($placeholders)){
$key = array_keys($placeholders)[0];
$values = array_pop($placeholders);
foreach($values => $value){
$inst = str_replace($uri, $key, $value);
$insts = array_merge($insts, (array)enumerate($inst, $placeholders));
}
return $insts;
} else {
return $uri;
}
}
Each call to the function pops one placeholder off the array and loops through its potential values enumerating through all the remaining placeholder values for each one. The complexity is O(k^n) where k is the average number of replacements for each placeholder and n is the number of placeholders.
My PHP is a little rusty; let me know if I got any of the syntax wrong.
foreach($placeholders['%foo%'] as $foo){
foreach($placeholders['%bar%'] as $bar){
$container[] = str_replace(array('%foo%','%bar%'),array($foo,$bar),$uri);
}
}
This work, but it's not so elegant because of the need to get rid of the placeholder array keys :
<?php
/*
* borrowed from http://www.theserverpages.com/php/manual/en/ref.array.php
* author: skopek at mediatac dot com
*/
function array_cartesian_product($arrays) {
//returned array...
$cartesic = array();
//calculate expected size of cartesian array...
$size = sizeof($arrays) > 0 ? 1 : 0;
foreach ($arrays as $array) {
$size *= sizeof($array);
}
for ($i = 0; $i < $size; $i++) {
$cartesic[$i] = array();
for ($j = 0; $j < sizeof($arrays); $j++) {
$current = current($arrays[$j]);
array_push($cartesic[$i], $current);
}
//set cursor on next element in the arrays, beginning with the last array
for ($j = sizeof($arrays) - 1; $j >= 0; $j--) {
//if next returns true, then break
if (next($arrays[$j])) {
break;
} else { //if next returns false, then reset and go on with previuos array...
reset($arrays[$j]);
}
}
}
return $cartesic;
}
$uri = "foo/bar?foo=%foo%&bar=%bar%";
$placeholders = array(
0 => array('a', 'b'), // '%foo%'
1 => array('c', 'd'), // '%bar%'
);
//example
header("Content-type: text/plain");
$prod = array_cartesian_product($placeholders);
$result = array();
foreach ($prod as $vals) {
$temp = str_replace('%foo%', $vals[0], $uri);
$temp = str_replace('%bar%', $vals[1], $temp);
array_push($result, $temp);
}
print_r($result);
?>

Categories