Dynamically create multidimensional array - php

I am trying to generate a multidimensional array, with a depth equal to the number of matches found in a regular expression. The array keys to be the string value of each match.
For example:
preg_match('/([A-Z])\-?([0-9])\-?([0-9]{1,3})/i', 'A-1-001', $matches);
Returns:
Array (
[0] => A-1-001
[1] => A
[2] => 1
[3] => 001
)
Which I want to convert to:
$foo = array(
'A' => array(
'1' => array(
'001' => array('some', 'information')
)
)
);
So that I can merge it with another multidimensional array like this:
$bar['A']['1']['001'] = array('some', 'other', 'information');
The process needs to handle any number of matches/dimensions.
Below is my current approach. I'm failing to grasp the concept, because this attempt falls way short of my goal.
$foo = array();
$j = count($matches);
for ($i = 1; $i < $j; $i++) {
$foo[ $matches[$i - 1] ] = $matches[$i];
}
/*
$foo's structure becomes:
Array (
[A-1-001] => A
[A] => 1
[1] => 001
)
*/
It's only swapping array keys, and not creating new children arrays I need.
Any suggestions or solutions would be greatly appreciated. Thanks!

With some PHP-Fu:
$matches = array('A-1-001', 'A', 1, '001');
$info = array('some', 'information');
print_r(tree($matches, $info));
function tree($array, $info){
$max = count($array)-1;
$result = array($array[$max] => $info);
for($i=$max-1;$i>0;$result = array($array[$i--] => $result));
return $result;
}
Output:
Array
(
[A] => Array
(
[1] => Array
(
[001] => Array
(
[0] => some
[1] => information
)
)
)
)

Well this could be done in a couple of ways, use of recursion for example. Now I had an other idea in my head. You flip the array with array_reverse. This way we can build from the back to the front.
And then we can setup everything. So the code would be something as followed
$foo = array();
$reversed = array_reverse($matches);
$some_info_array = array('some', 'information');
foreach($reversed as $key) {
if(empty($foo)) {
$foo[$key] = $some_info_array;
} else {
$foo[$key] = $foo;
}
}
code not tested but should give you a nive idea/start

Given the original array:
$original_array = array( 'A-1-001', 'A', '1', '001' );
You can convert it to the format you described like this:
$new_array[ $original_array[1] ] = array( $original_array[2] => $original_array[3] );
This yields
array(1) {
["A"]=>
array(1) {
[1]=>
string(3) "001"
}
}
You can then assign values to that array as you indicated:
$new_array['A']['1']['001'] = array('some', 'information');

You could use a function like this ... it should cover any depth. Bonus is that you can keep passing the value of $tree to more branches and get a single tree with multiple products.
function arrayToTree($array, &$tree, $addlAttribs){
$node = array_shift($array);
if (count($array)){
// this is a branch
$tree[$node] = array();
return arrayToTree($array, $tree[$node]);
} else {
$tree[$node] = $addlAttribs;
return;
}
}
You would use it like
$t = array();
array_shift($matches); // remove the first match "A-1-001"
arrayToTree($matches, $tree, $productInfo);
print_r($tree);

Related

FOR-EACH control structures with an array display only the last value [duplicate]

I have an associative array, however when I add values to it using the below function it seems to overwrite the same keys. Is there a way to have multiple of the same keys with different values? Or is there another form of array that has the same format?
I want to have:
42=>56
42=>86
42=>97
51=>64
51=>52
etc etc
Code:
function array_push_associative(&$arr) {
$args = func_get_args();
foreach ($args as $arg) {
if (is_array($arg)) {
foreach ($arg as $key => $value) {
$arr[$key] = $value;
$ret++;
}
}else{
$arr[$arg] = "";
}
}
return $ret;
}
No, you cannot have multiple of the same key in an associative array.
You could, however, have unique keys each of whose corresponding values are arrays, and those arrays have multiple elements for each key.
So instead of this...
42=>56 42=>86 42=>97 51=>64 51=>52
...you have this:
Array (
42 => Array ( 56, 86, 97 )
51 => Array ( 64, 52 )
)
A key is an extension of a variable. If you overwrite the variable... You overwrite the variable.
No, you cannot have. A workaround I use is to have each key/value pair as a new array with 2 elements:
$test = array(
array(42,56),
array(42,86),
array(42,97),
array(51,64),
array(51,52)
)
For example, you can access the second key (=42) using:
$test[1][0]
and the second value(=86) using:
$test[1][1]
I found this question while researching the exact opposite intended outcome, I have an array of data that has duplicate keys! Here's how I did it (still trying to figure out where in my process things are messing up).
$session = time();
$a = array();
$a[(string)$session] = 0;
$j = json_encode($a,JSON_FORCE_OBJECT);
print_r($a);
/* output:
Array
(
[1510768034] => 0
)
*/
var_dump($a);
/* output:
array(1)
(
[1510768034] => int(0)
)
*/
print_r($j);
/* output:
{"1510768034":0}
*/
$a = (array)json_decode($j);
$session = #array_pop(array_keys($a));
$a[(string)$session] = 10;
$j = json_encode($a,JSON_FORCE_OBJECT);
print_r($a);
/* output:
Array
(
[1510768034] => 0
[1510768034] => 10
)
*/
var_dump($a);
/* output:
array(2)
(
'1510768034' => int(0)
[1510768034] => int(10)
)
*/
print_r($j);
/* output:
{"1510768034":0,"1510768034":10}
*/
Yup....that just happened.
PHP 7.1
Edit: It's similar in PHP 7.2.10, except json_encode no longer entertains duplicate keys, encoded strings are correct. The array, however, can have matching string and integer keys.
i had the same need too create an array with the same keys, (just to keep performance by using two loops rather than 4 loops).
by using this : [$increment."-".$domain_id] => $article_id;
my list of articles in each domain looks like this after a print_r() :
$AllSa = Array
(
[1-5] => 143
[2-5] => 176
[3-5] => 992
[4-2] => 60
[5-2] => 41
[6-2] => 1002
[4-45] => 5
[5-45] => 18
[6-45] => 20
)
And then by looping through this table to associate article by domain :
$AssocSAPerDomain = array();
$TempDomain = "";
$TempDomain_first = 0;
foreach($tree_array as $id_domain => $id_sa){
if( !$TempDomain && $TempDomain_first == 0 ){ $TempDomain = substr(strrchr($id_domain, "-"), 1); $TempDomain_first = 1; }
$currentDomain = substr(strrchr($id_domain, "-"), 1);
//if($TempDomain == $currentDomain)
$AssocSAPerDomain[$currentDomain][] = $id_sa;
$TempDomain = substr(strrchr($id_domain, "-"), 1);
}
you get this
$assoc= Array
(
[5] => 143
=> 176
=> 992
[2] => 60
=> 41
=> 1002
[45]=> 5
=> 18
=> 20
)
it is not possible technically. But I created a fun way to do it. Be alert, this answer is just for the fun, the ultimate goal is to get the output anyway.
So here is the answer. You first need to convert to the whole array to the string. Then the rest of the things is just string replace and a little code.
<?php
$ary="array('a'=>123,'a'=>161,'a'=>195)";
$str = str_replace("array(", "", $ary);
$str = str_replace(")", "", $str);
$arr = explode(",",$str);
foreach($arr as $element){
$element = str_replace("=>", "", $element);
$element = str_replace("'", "", $element);
echo $element.'<br>';
}
?>
Here is the output

Remove duplicate keys from array? [duplicate]

I have an associative array, however when I add values to it using the below function it seems to overwrite the same keys. Is there a way to have multiple of the same keys with different values? Or is there another form of array that has the same format?
I want to have:
42=>56
42=>86
42=>97
51=>64
51=>52
etc etc
Code:
function array_push_associative(&$arr) {
$args = func_get_args();
foreach ($args as $arg) {
if (is_array($arg)) {
foreach ($arg as $key => $value) {
$arr[$key] = $value;
$ret++;
}
}else{
$arr[$arg] = "";
}
}
return $ret;
}
No, you cannot have multiple of the same key in an associative array.
You could, however, have unique keys each of whose corresponding values are arrays, and those arrays have multiple elements for each key.
So instead of this...
42=>56 42=>86 42=>97 51=>64 51=>52
...you have this:
Array (
42 => Array ( 56, 86, 97 )
51 => Array ( 64, 52 )
)
A key is an extension of a variable. If you overwrite the variable... You overwrite the variable.
No, you cannot have. A workaround I use is to have each key/value pair as a new array with 2 elements:
$test = array(
array(42,56),
array(42,86),
array(42,97),
array(51,64),
array(51,52)
)
For example, you can access the second key (=42) using:
$test[1][0]
and the second value(=86) using:
$test[1][1]
I found this question while researching the exact opposite intended outcome, I have an array of data that has duplicate keys! Here's how I did it (still trying to figure out where in my process things are messing up).
$session = time();
$a = array();
$a[(string)$session] = 0;
$j = json_encode($a,JSON_FORCE_OBJECT);
print_r($a);
/* output:
Array
(
[1510768034] => 0
)
*/
var_dump($a);
/* output:
array(1)
(
[1510768034] => int(0)
)
*/
print_r($j);
/* output:
{"1510768034":0}
*/
$a = (array)json_decode($j);
$session = #array_pop(array_keys($a));
$a[(string)$session] = 10;
$j = json_encode($a,JSON_FORCE_OBJECT);
print_r($a);
/* output:
Array
(
[1510768034] => 0
[1510768034] => 10
)
*/
var_dump($a);
/* output:
array(2)
(
'1510768034' => int(0)
[1510768034] => int(10)
)
*/
print_r($j);
/* output:
{"1510768034":0,"1510768034":10}
*/
Yup....that just happened.
PHP 7.1
Edit: It's similar in PHP 7.2.10, except json_encode no longer entertains duplicate keys, encoded strings are correct. The array, however, can have matching string and integer keys.
i had the same need too create an array with the same keys, (just to keep performance by using two loops rather than 4 loops).
by using this : [$increment."-".$domain_id] => $article_id;
my list of articles in each domain looks like this after a print_r() :
$AllSa = Array
(
[1-5] => 143
[2-5] => 176
[3-5] => 992
[4-2] => 60
[5-2] => 41
[6-2] => 1002
[4-45] => 5
[5-45] => 18
[6-45] => 20
)
And then by looping through this table to associate article by domain :
$AssocSAPerDomain = array();
$TempDomain = "";
$TempDomain_first = 0;
foreach($tree_array as $id_domain => $id_sa){
if( !$TempDomain && $TempDomain_first == 0 ){ $TempDomain = substr(strrchr($id_domain, "-"), 1); $TempDomain_first = 1; }
$currentDomain = substr(strrchr($id_domain, "-"), 1);
//if($TempDomain == $currentDomain)
$AssocSAPerDomain[$currentDomain][] = $id_sa;
$TempDomain = substr(strrchr($id_domain, "-"), 1);
}
you get this
$assoc= Array
(
[5] => 143
=> 176
=> 992
[2] => 60
=> 41
=> 1002
[45]=> 5
=> 18
=> 20
)
it is not possible technically. But I created a fun way to do it. Be alert, this answer is just for the fun, the ultimate goal is to get the output anyway.
So here is the answer. You first need to convert to the whole array to the string. Then the rest of the things is just string replace and a little code.
<?php
$ary="array('a'=>123,'a'=>161,'a'=>195)";
$str = str_replace("array(", "", $ary);
$str = str_replace(")", "", $str);
$arr = explode(",",$str);
foreach($arr as $element){
$element = str_replace("=>", "", $element);
$element = str_replace("'", "", $element);
echo $element.'<br>';
}
?>
Here is the output

Get specific content from a string

I need to get numbers as an array from a given string.
Example string:
$t = '1-P,2-T,3-P,4-R,5-C,6-T,';
Expected output:
if I search -T the output needs to be like this:
array(
[0] => 2,
[1] => 6
)
if it's -P:
array(
[0] => 1,
[1] => 3
)
I tried var_export(explode("-T,",$t)); but it didn't work as expected.
Can any one give me a suggestion to get this?
The below matches the full integer number which preceeds the search term -P.
Let's keep it concise:
$matches = array();
if (preg_match_all('/([0-9]+)\-P/', $t, $matches) >= 1) {
var_dump($matches[1]);
}
Search for '/([0-9]+)\-P/, '/([0-9]+)\-C/, '/([0-9]+)\-T/ an so on.
A more dynamic way to look for different search terms/filters:
$filter = '-T';
$pattern = sprintf('/([0-9]+)%s/', preg_quote($filter));
See preg_match_all and preg_quote functions.
Try this:
$t = '211111111131-P,2-T,3654554-P,4-R,5-C,6-T,';
$find = "-P"; // Search element
$found = []; // Result array
$array = explode(",", $t); // Breaking up into array
foreach($array as $arr) {
if (strpos($arr, $find)) { // Checking if search element is found in $arr
$found[] = explode('-',$arr)[0]; // Extracting the number prefix e.g 1 for 1-P
}
}
Output:
Array
(
[0] => 1
[1] => 3
)
Use it as
$t = '1-P,2-T,3-P,4-R,5-C,6-T,';
$data = explode(",", $t);
print_r($data);
$row=array();
for ($i = 0; $i <= count($data); $i++) {
if (!empty($data[$i])) {
if (strpos($data[$i], '-T') !== false) {// pass find value here
$final = explode("-", $data[$i]);
$row[]=$final[0];
}
}
}
print_r($row);
Output
Array
(
[0] => 2
[1] => 6
)
DEMO
$t = '1-P,2-T,3-P,4-R,5-C,6-T,';
$temp = [];
// if the last comma is not typo the 3rd argument `-1` omit empty item
$array = explode(",", $t, -1);
foreach($array as $arr) {
list($v, $k) = explode('-', $arr);
$temp[$k][] = $v;
}
print_r($temp['T']);
demo
Lots of good answers here already, but none take the approach of first putting the data into a better structure.
The code below converts the data to an associative array mapping letters to arrays of numbers, so that you can then do repeated lookups by whichever letter you want:
$t = '1-P,2-T,3-P,4-R,5-C,6-T,';
$a = array_filter(explode(',', $t));
$map = [];
foreach($a as $item) {
$exploded = explode('-', $item);
$number = $exploded[0];
$letter = $exploded[1];
if (!array_key_exists($letter, $map)) {
$map[$letter] = [];
}
$map[$letter][] = $number;
}
print_r($map);
// Array
// (
// [P] => Array
// (
// [0] => 1
// [1] => 3
// )
//
// [T] => Array
// (
// [0] => 2
// [1] => 6
// )
//
// [R] => Array
// (
// [0] => 4
// )
//
// [C] => Array
// (
// [0] => 5
// )
//
// )
print_r($map['T']);
// Array
// (
// [0] => 2
// [1] => 6
// )
print_r($map['P']);
// Array
// (
// [0] => 1
// [1] => 3
// )

Storing value in unknown depth of multidimensional array

I have this exath path saved somewhere:
Array
(
[0] => library
[1] => 1
[2] => book
[3] => 0
[4] => title
[5] => 1
)
I have some array and I want to change the value on this index:
$values[library][1][book][0][title][1] = "new value";
I have no idea, how to do this, because there can be any (unknown) number of dimensions. Any hints?
It makes sense to create a function that does this, so:
function array_path_set(array & $array, array $path, $newValue) {
$aux =& $array;
foreach ($path as $key) {
if (isset($aux[$key])) {
$aux =& $aux[$key];
} else {
return false;
}
}
$aux = $newValue;
return true;
}
$values = array(
'library' => array(
1 => array(
'book' => array(
0 => array(
'title' => array(
1 => 'MAGIC VALUE!',
),
),
),
),
),
);
$path = array('library', 1, 'book', 0, 'title', 1);
$newValue = 'ANOTHER MAGIC VALUE!';
var_dump($values);
var_dump(array_path_set($values, $path, $newValue));
var_dump($values);
Try
foreach ($array as $val) {
$indexes .= "[$val]";
}
${'output'.$indexes} = 'something';
Or
$indexes = '';
foreach ($array as $val) {
$indexes .= "[$val]";
}
$output = 'values'.$indexes;
$$output = 'something';
Are you trying to provide a new value for the title of book 0 in library 1? If so, you will have to search for library "1", with book "0" and then change the value of the "title". So if all your values in the array have the same six entries, start with loc = 0 look at the values at loc+1 (library id), loc+3 (book id) and loc+5 .. change title) .. if not increment loc by 6 and continue searching.
[sounds like homework, so no code provided. Pardon me if I am wrong.]
Just in case you weren't aware of it, the key
$values["library"][1]["book"][0]["title"][1]
Is not the same as the array example in your post. Presuming the array is $values, it has five elements:
$values = Array
(
[0] => "library"
[1] => 1
[2] => "book"
[3] => 0
[4] => "title"
[5] => 1
)
$values[0] = "Library";
$values[1] = "1";
$values[2] = "book";
$values[3] = "0";
etc...
Is this array structure what you intended? If not, post back with a more complete structure so we can help.
Also, you need quotes around the strings - I have included for clarity
You could take a look at the following link for array_search. Some of the posters have included examples of a multidimensional array search and there are other examples. Do a google search on "multidimensional array search" and you will likely find a solution. If you need more direction, post back your details.
try this ->
$keys = array('0'=>'for','1'=>'test','2'=>'only');
$value='ok';
function addArrayPathWithValue($keys,$value,$array = array(),$current =
array())
{
$function = __FUNCTION__;
if (count($current)==0)
{
$keys = array_reverse($keys);
$current = $value;
}
if (count($keys)==0)
{
return $current;
}
$array[array_shift($keys)]=$current;
return $function($keys,$value,NULL,$array);
}
$array = addArrayPathWithValue($keys,$value);
print_r($array);
//output: Array ( [for] => Array ( [test] => Array ( [only] => ok ) ) )

PHP Associative Array Duplicate Keys

I have an associative array, however when I add values to it using the below function it seems to overwrite the same keys. Is there a way to have multiple of the same keys with different values? Or is there another form of array that has the same format?
I want to have:
42=>56
42=>86
42=>97
51=>64
51=>52
etc etc
Code:
function array_push_associative(&$arr) {
$args = func_get_args();
foreach ($args as $arg) {
if (is_array($arg)) {
foreach ($arg as $key => $value) {
$arr[$key] = $value;
$ret++;
}
}else{
$arr[$arg] = "";
}
}
return $ret;
}
No, you cannot have multiple of the same key in an associative array.
You could, however, have unique keys each of whose corresponding values are arrays, and those arrays have multiple elements for each key.
So instead of this...
42=>56 42=>86 42=>97 51=>64 51=>52
...you have this:
Array (
42 => Array ( 56, 86, 97 )
51 => Array ( 64, 52 )
)
A key is an extension of a variable. If you overwrite the variable... You overwrite the variable.
No, you cannot have. A workaround I use is to have each key/value pair as a new array with 2 elements:
$test = array(
array(42,56),
array(42,86),
array(42,97),
array(51,64),
array(51,52)
)
For example, you can access the second key (=42) using:
$test[1][0]
and the second value(=86) using:
$test[1][1]
I found this question while researching the exact opposite intended outcome, I have an array of data that has duplicate keys! Here's how I did it (still trying to figure out where in my process things are messing up).
$session = time();
$a = array();
$a[(string)$session] = 0;
$j = json_encode($a,JSON_FORCE_OBJECT);
print_r($a);
/* output:
Array
(
[1510768034] => 0
)
*/
var_dump($a);
/* output:
array(1)
(
[1510768034] => int(0)
)
*/
print_r($j);
/* output:
{"1510768034":0}
*/
$a = (array)json_decode($j);
$session = #array_pop(array_keys($a));
$a[(string)$session] = 10;
$j = json_encode($a,JSON_FORCE_OBJECT);
print_r($a);
/* output:
Array
(
[1510768034] => 0
[1510768034] => 10
)
*/
var_dump($a);
/* output:
array(2)
(
'1510768034' => int(0)
[1510768034] => int(10)
)
*/
print_r($j);
/* output:
{"1510768034":0,"1510768034":10}
*/
Yup....that just happened.
PHP 7.1
Edit: It's similar in PHP 7.2.10, except json_encode no longer entertains duplicate keys, encoded strings are correct. The array, however, can have matching string and integer keys.
i had the same need too create an array with the same keys, (just to keep performance by using two loops rather than 4 loops).
by using this : [$increment."-".$domain_id] => $article_id;
my list of articles in each domain looks like this after a print_r() :
$AllSa = Array
(
[1-5] => 143
[2-5] => 176
[3-5] => 992
[4-2] => 60
[5-2] => 41
[6-2] => 1002
[4-45] => 5
[5-45] => 18
[6-45] => 20
)
And then by looping through this table to associate article by domain :
$AssocSAPerDomain = array();
$TempDomain = "";
$TempDomain_first = 0;
foreach($tree_array as $id_domain => $id_sa){
if( !$TempDomain && $TempDomain_first == 0 ){ $TempDomain = substr(strrchr($id_domain, "-"), 1); $TempDomain_first = 1; }
$currentDomain = substr(strrchr($id_domain, "-"), 1);
//if($TempDomain == $currentDomain)
$AssocSAPerDomain[$currentDomain][] = $id_sa;
$TempDomain = substr(strrchr($id_domain, "-"), 1);
}
you get this
$assoc= Array
(
[5] => 143
=> 176
=> 992
[2] => 60
=> 41
=> 1002
[45]=> 5
=> 18
=> 20
)
it is not possible technically. But I created a fun way to do it. Be alert, this answer is just for the fun, the ultimate goal is to get the output anyway.
So here is the answer. You first need to convert to the whole array to the string. Then the rest of the things is just string replace and a little code.
<?php
$ary="array('a'=>123,'a'=>161,'a'=>195)";
$str = str_replace("array(", "", $ary);
$str = str_replace(")", "", $str);
$arr = explode(",",$str);
foreach($arr as $element){
$element = str_replace("=>", "", $element);
$element = str_replace("'", "", $element);
echo $element.'<br>';
}
?>
Here is the output

Categories