I have a multidimensional array like this:
$array1['first']='myvalue1';
$array1['second']=array();
$array1['second']['first']='myvalue21';
$array1['second']['second']='myvalue22';
$array1['second']['third']=array();
$array1['second']['third']['first']='myvalue231';
$array1['second']['fourth']='myvalue24';
$array1['third']='myvalue3';
And another array like:
$array2['second-first']='newvalue21';
$array2['second-third-first']='newvalue231';
And I can't get the way to walk $array1 recursively to check, in each iteration, if exist any element in $array2 with a key equivalent to the current element key and their parents converted to string.
To simplify the question, I will have enough with a function that prints something like:
// walking $array1:
first
second-first
second-second
second-third-first
second-fourth
third
Thank you.
Solution based on Clément Malet answer
function print_array_reccur ($array1, $array2, $str = '')
{
foreach ($array1 as $key => $val) {
if (is_array($val)) {
if ($str == '') {
print_array_reccur($val, $array2, $key);
} else {
print_array_reccur($val, $array2, $str . '-' . $key);
}
} else {
if ($str == '') {
$result = $key;
} else {
$result = $str . '-' . $key;
}
if(isset($array2[$result]))
{
echo 'Found $array2['.$result.'] = ' . $array2[$result] . "\n";
}
}
}
}
print_array_reccur ($array1, $array2);
/* OUTPUT:
Found $array2[second-first] = newvalue21
Found $array2[second-third-first] = newvalue231
*/
I really didn't understand what you wanted in the very end, and what you want to achieve later on with your second array.
But since you are looking for a way to print something (glad you simplified that way), here it is :
$array1['first']='myvalue1';
$array1['second']=array();
$array1['second']['first']='myvalue21';
$array1['second']['second']='myvalue22';
$array1['second']['third']=array();
$array1['second']['third']['first']='myvalue231';
$array1['second']['fourth']='myvalue24';
$array1['third']='myvalue3';
function print_array_reccur ($array, $str = '') {
foreach ($array as $key => $val) {
if (is_array($val)) {
if ($str == '') {
print_array_reccur($val, $key);
} else {
print_array_reccur($val, $str . '-' . $key);
}
} else {
if ($str == '') {
echo $key . "\n";
} else {
echo $str . '-' . $key . "\n";
}
}
}
}
print_array_reccur ($array1);
Output :
first
second-first
second-second
second-third-first
second-fourth
third
Related
I want to cut text in array but I have no idea to cut this
I try strstr() but it not true.
I try
$ff='';
while($row = mysqli_fetch_array($result,MYSQLI_ASSOC)){
$ff .= $row['fav'] . ",";
}
if( strpos( $ff, "_" )) {
$text = strstr($ff, '_');
echo $text;
}
$ff ='A_0089,A_5677,B_4387,A_B_5566,'
I want output show
0089,5677,4387,B_5566,
Here is one example, using substr() with strpos():
$ff='A_0089,A_5677,B_4387,A_B_5566';
$items = explode(',', $ff);
foreach($items as $item) {
echo substr($item, strpos($item, '_')) . "\n";
}
The above code returns:
_0089
_5677
_4387
_B_5566
You're better off not building a string, but building an array. The way you build the string you have a dangling comma, which you do not want.
$ff = array();
while($row = mysqli_fetch_array($result,MYSQLI_ASSOC)){
$ff[] = $row['fav'];
}
foreach($ff as $item) {
echo substr($item, strpos($item, '_')) . "\n";
}
Based on your desire to keep the commas and create a string:
$ff='A_0089,A_5677,B_4387,A_B_5566,';
$items = explode(',', $ff);
foreach($items as $item) {
$new[] = substr($item, strpos($item, '_'));
}
$newFF = implode(',', $new);
echo $newFF;
returns:
_0089,_5677,_4387,_B_5566,
Probably this is what you are looking for
<?php
function test_alter(&$item1)
{
$pattern = '/^[A-Z]{1}[_]{1}/';
$item1 =preg_replace($pattern,"",$item1);
}
$ff="A_0089,A_5677,B_4387,A_B_5566,";
$nff=explode(",",$ff);
array_walk($nff, 'test_alter');
echo implode(",",$nff);
?>
I have a array of val which has dynamic strings with underscores. Plus I have a variable $key which contains an integer. I need to match $key with each $val (values before underscore).
I did the following way:
<?php
$key = 2; //always a dynamic number
$val = array('3_33', '2_55'); //always a dynamic string with underscore
if(in_array($key, $val)) {
echo 'Yes';
}
else
{
echo 'No';
}
?>
Though this code works fine, I want to know if its a correct way or suggest some better alternative.
use this function for regex match from php.net
function in_array_match($regex, $array) {
if (!is_array($array))
trigger_error('Argument 2 must be array');
foreach ($array as $v) {
$match = preg_match($regex, $v);
if ($match === 1) {
return true;
}
}
return false;
}
and then change your code to use this function like this:
$key = 2; //always a dynamic number
$val = array('3_33', '2_55'); //always a dynamic string with underscore
if(in_array_match($key."_*", $val)) {
echo 'Yes';
}
else
{
echo 'No';
}
This should work :
foreach( $val as $v )
{
if( strpos( $v , $key .'_' ) === true )
{
echo 'yes';
}
else {
echo 'no';
}
}
you can use this
function arraySearch($find_me,$array){
$array2 =array();
foreach ($array as $value) {
$val = explode('_',$value);
$array2[] =$val[0];
}
$Key = array_search($find_me, $array2);
$Zero = in_array($find_me, $array2);
if($Key == NULL && !$Zero){
return false;
}
return $Key;
}
$key = 2; //always a dynamic number
$val = array('3_33', '2_55'); //always a dynamic string with underscore
$inarray = false;
foreach($val as $v){
$arr = explode("_", $val);
$inarray = $inarray || $arr[0] == $key
}
echo $inarray?"Yes":"No";
The given format is quite unpractically.
$array2 = array_reduce ($array, function (array $result, $item) {
list($key, $value) = explode('_', $item);
$result[$key] = $value;
return $result;
}, array());
Now you can the existence of your key just with isset($array2[$myKey]);. I assume you will find this format later in your execution useful too.
I currently have coded a way to turn a multidimensional array to comma separated values (I'm using pipes instead of commas for ease of debugging). The problem is, I know that the code I use to do this is bloody awful. It works how I want it to, but it's not nice at all.
What I need
Currently the arr_to_csv() function works for five levels of nested data within the multidimensional array. I need a recursive function to perform the same for one or an unlimited number of nested arrays, or a good nudge in the right direction. Recursion is not my strong point at all, but I know it's the way forward.
Data input
A multi-dimensional array is passed to the function.
array
'name' =>
array
'singular' => null
'plural' => null
'fields' =>
array
'price' =>
array
'label' => string 'Preis' (length=5)
'company_id' =>
array
'label' => null
'placeholder' => null
//...the array could go on...
The function returns the following...
This is exactly what I want...
0 => string 'name||singular||null' (length=20)
1 => string 'name||plural||null' (length=18)
2 => string 'fields||price||label||Preis' (length=27)
3 => string 'fields||company_id||label||null' (length=31)
4 => string 'fields||company_id||placeholder||null' (length=37)
5 => string 'fields||name||label||null' (length=25)
6 => string 'fields||name||placeholder||null' (length=31)
My horrible constructed function
I'm no good with recursion, so here's my awful list of foreachs. As you can see from the below code, this is terrible (no need to read the whole thing, it just copies itself). Please help me sort out my horrible code!
function arr_to_csv($data,$csv = '||') {
$array = array();
/* Epic amount of for each's. This could be done with recursion */
foreach($data as $key => &$value) {
if (!is_array($value)) {
$array[] = $key . $csv .(is_null($value)?'null':$value);
} else {
foreach ($value as $k => &$v) {
if (!is_array($v)) {
$array[] = $key . $csv . $k . $csv . (is_null($v) ? 'null' : $v);
} else {
foreach ($v as $kk => &$vv) {
if (!is_array($vv)) {
$array[] = $key . $csv . $k . $csv . $kk . $csv . (is_null($vv) ? 'null' : $vv);
} else {
foreach ($vv as $x => &$y) {
if (!is_array($y)) {
$array[] = $key . $csv . $k . $csv . $kk . $csv. $x . $csv . (is_null($y) ? 'null' : $y);
} else {
foreach ($y as $too => $long) {
if(!is_array($long)) {
$array[] = $key . $csv . $k . $csv . $kk . $csv. $x . $csv . $too . $csv. (is_null($long)?'null':$long);
} else {
foreach ($long as $omg => $why) {
if(!is_array($why)) {
$array[] = $key . $csv . $k . $csv . $kk . $csv. $x . $csv . $too . $csv . $omg . $csv . (is_null($why) ? 'null' : $why);
}
}
}
}
}
}
}
}
}
}
}
}
return $array;
}
This is some pseudocode, but it is a start:
$strings = [];
$flattenArray = function($arr, $level) use (&$strings, &$flattenArray) {
foreach($arr as $key=>$value){
$s = &$strings[$level];
if(!isset($s)) { $s = array(); }
$s[] = $key;
if(is_array($value)) {
$flattenArray($value, $level);
}
else {
$s[] = $value;
}
$level ++;
}
};
$flattenArray($myArray, 0);
foreach($strings as &$arr) {
$arr = implode("||", $arr);
}
Small demo with your array: http://codepad.viper-7.com/CR2SPY <-- It does not work fully, but it is a start
Update:
Here is a demo that I think works the way you want: http://codepad.viper-7.com/shN4pH
Code:
$strings = [];
$flattenArray = function($arr, $level, $k = null) use (&$strings, &$flattenArray) {
foreach($arr as $key=>$value){
if($k === null) {
$s = &$strings[$key];
}
else {
$s = &$strings[$k];
}
if(!isset($s)) {
$s = array();
}
$str = &$s[$level];
if(!isset($str)) {
$str = array();
if($k !== null) { $str[] = $k; }
}
$str[] = $key;
if(is_array($value)) {
$flattenArray($value, $level, ($k === null) ? $key : $k);
}
else {
$str[] = is_null($value) ? "null" : $value;
}
$level ++;
}
};
$flattenArray($myArray, 0);
$all = [];
foreach($strings as $k => $arr){
$new = array();
foreach($arr as $ky => $ar) {
$all[] = implode("||", $ar);
}
}
print_r($all);
I didn't check it, so in case it doesn't work it should be corrected.
function readarray($from_array, $addr = array()) {
global $output;
foreach ($from_array as $key => $value) {
if (is_Array($value) && count($value) > 0) {
$addr[] = $key;
readarray($value, $addr);
} else {
$output[] = implode('||', $addr) . $value;
}
}
}
$output = array();
foreach ($my_array as $key=>$value){
readarray($value);
}
// improved to get separate arrays of the root of initial array
Not sure if this will help you, but would it not be easier to flatten the array first and then format in in the way you want? To flatten the array try this:
$array = "YOUR ARRAY";
$FlatArray = array();
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $k=>$v)
{
$FlatArray[$k] = $v;
}
Been trying all morning to come up with a recursive function for this. This is as close as I got, Maybe you can improve upon this.
$data = array('name' =>array('singular' => NULL,'plural' => NULL,'fields' =>array('price' =>array('label' =>'Preis','company_id' =>array('label' => NULL,'placeholder' => NULL)))));
function arr_to_csv($data,$csv = '||')
{
$list = "";
foreach($data as $key => &$value)
{
$list .= $key . $csv .((!is_array($value))?(is_null($value)?'null':$value): arr_to_csv($value))."<br>";
}
return $list;
}
print_r(arr_to_csv($data));
Returns This:
name||singular||null
plural||null
fields||price||label||Preis
company_id||label||null
placeholder||null
while($row=mysql_fetch_assoc($query)) {
$id = $row['id'];
$col1 = $row['name1'];
$col2= $row['name2'];
$col3= $row['name3'];
${"$id"} = array("$col1","$col2","$col3");
${"$s".$i}[] = ${"$id"};
}
This is just a breif example of what i'm trying to accomplish, $i is incremented somewhere else. I'm trying to implode the arrays in the array. So below I have imploded the main array but how do I implode the other arrays?
for($i=0;$i<11;$i++) {
$array = ${"s" . $i};
$outcomes = implode("",$array); //implodes main array
}
Not quite sure what you are trying to achieve here, but does this help?
function recursive_echo ($arr, $spacing = 0) {
$padding = ($spacing) ? str_pad('', $spacing) : '';
foreach ($arr as $key => $val) {
if (is_array($val)) {
echo "{$padding}{$key}:<br />\n";
recursive_echo($val, $spacing + 2);
} else {
echo "{$padding}{$val}<br />\n";
}
}
}
This function just echoes out the data, but it illustrates how to recurse through a multi-dimensional array where the number of dimensions is unknown.
I want to build a hierarchy from a one-dimensional array and can (almost) do so with a more or less hardcoded code. How can I make the code dynamic?
Perhaps with while(isset($array[$key])) { ... }?
Or, with an extra function? Like this: $out = my_extra_traverse_function($array,$key);
function array_traverse($array,$key=NULL) {
$out = (string) $key;
$out = $array[$key] . "/" . $out;
$key = $array[$key];
$out = $array[$key] ? $array[$key] . "/" . $out : "";
$key = $array[$key];
$out = $array[$key] ? $array[$key] . "/" . $out : "";
$key = $array[$key];
$out = $array[$key] ? $array[$key] . "/" . $out : "";
return $out;
}
$a = Array(102=>101, 103=>102, 105=>107, 109=>105, 111=>109, 104=>111);
echo array_traverse($a,104);
Output: 107/105/109/111/104
I THINK you want:
function array_traverse($array, $key = null) {
$out = (string) $key;
if (isset($array[$key])) {
$out = array_traverse($array, $array[$key]) . '/' . $out;
}
return $out;
}
Or, for a non-recursive method:
function array_traverse($array, $key = null) {
$out = (string) $key;
while(isset($array[$key])) {
$out = $array[$key] . '/' . $out;
$key = $array[$key];
}
return $out;
}
Yes, I would say isset() is the way to go:
traverse($array, $value) {
$result = array();
while (isset($array[$value])) {
array_unshift($result, $value);
# or just $result[] = $value if you want to append
# instead of prepending
$value = $array[$value];
}
return $result;
# or return implode('/', traverse(array(...))),
# but I always prefer array return types in such cases:
# they are much more flexible to the users of the function
}
# BTW: Using implode will avoid having an unnecessary
# leading/trailing delimiter (slash in this case)
echo implode('/', traverse(array(...)));