I'm looking for niftier check if multidim. array $a matches pattern (key/value) in multidim. array $b (or in other words, check if $b is a subarray of $a). My recursive traversal code with trace help attached below, ready to paste in an empty script.
This is needed to filter mdim array of products using mdim array of its chosen properties to match.
Any simplification appreciated.
<pre>
<?php
$a = array (
"a" => "1",
"b" => "red",
"c" => array(
"ca" => "ca123",
"cb" => "cb123",
),
"d" => array(
"da" => "da123",
"db" => "db123",
"dc" => array(
"dca" => "dca123",
"dcb" => "dcb123"
),
),
);
$b = array(
"b" => "red",
"c" => array(
"ca" => "ca123",
),
"d" => array(
"dc" => array(
"dca" => "dca123",
),
),
);
function is_subarray(&$needle = array(), &$haystack = array())
{
if (!$needle || !$haystack || !is_array($needle) || !is_array($haystack)) return FALSE;
echo __FUNCTION__ . " ENTRY ****************************************************************<br />";
echo "Needle: " . print_r($needle, TRUE) . "<br />Haystack: " . print_r($haystack, TRUE) . "<br />";
foreach ($needle as $needle_key => $needle_value) {
echo "Analyzing needle pair: " . print_r(array($needle_key => $needle_value), TRUE) . "<br />";
echo "and haystack: " . print_r($haystack, TRUE) . "<br />";// . print_r($needle_value, true) . "<br />";
if (array_key_exists($needle_key, $haystack) && (gettype($needle_value) == gettype($haystack[$needle_key]))) {
// Keys matches and values type matches
echo "Keys matches and values type matches<br />";
if (is_array($needle_value)) {
// Values are arrays - going deeper
echo "Values are arrays - going deeper<br />";
if (!is_subarray($needle_value, $haystack[$needle_key])) return FALSE;
} else if ($needle_value != $haystack[$needle_key]) {
// Values don't match - this is the end
echo "Values don't match - this is the end<br />";
return FALSE;
} else {
// Values do match
echo "Values do match<br />";
//$result = true;
}
} else {
// No key found - this is the end
echo "No key found - this is the end<br />";
return FALSE;
}
}
echo __FUNCTION__ . "**************************************************************** EXIT<br />";
return TRUE;
}
echo "<br />Match: " . ((is_subarray($b, $a)) ? "YES" : "NO");
?>
</pre>
Related
I have an array as follows:
$list_array = array();
$list_array[] = array (
'id' => 1,
'name' => 'Sean',
'codename' => 'Maverick'
);
$list_array[] = array (
'id' => 2,
'name' => 'Matt',
'codename' => 'Diesel'
);
$list_array[] = array (
'id' => 3,
'name' => 'Bonnie',
'codename' => 'Princess'
);
I am trying to figure out how I can check to see if it's empty. I look on the site and tried a couple of things, but it's not working. Here are the things I've tried.
Attempt 1:
if (empty($list_array)
echo "Array is empty";
Attempt 2:
$arr_empty = true;
$arr_length = count($list_array);
echo "Length: " . $arr_length . "<br>";
for ($z=1; $z<=$arr_length; $z++)
{
$arr_length2 = count($list_array[$z]);
echo $z . " Length2: " . $arr_length2 . "<br>";
if (empty($list_array[$z]))
echo $z . " Is Empty<br>";
}
I feel like I'm missing the obivious here.
There are a few PHP functions for this that all do slightly different things:
isset — Determine if a variable is set and is not NULL
Example:
if(isset($list_array)){//do something} will do something if $list_array is set to a value other than NULL.
See: http://uk3.php.net/manual/en/function.isset.php
empty — Determine whether a variable is empty. This function returns true if the variable or array is an empty string, false, array(), NULL, 0 or an unset variable. I prefer the use of the empty function.
Example:
if(!empty($list_array)){
//do something with array here, such as a foreach or while loop.
}
See: http://uk3.php.net/empty
is_null — Identifies whether or not a variable is NULL by returning either true or false. It returns true only when the variable is null. is_null() is opposite of isset(), except for one difference that isset() can also be applied to unknown variables whereas is_null() can only be used for declared variables.
Example:
if(is_null($var)){ //do something }
See: http://uk3.php.net/manual/en/function.is-null.php
Let's stick with empty:
if(empty($list_array)){ $msg = "Array is empty!"; }
if(!isset($msg)){echo $msg;}
empty should work:
if (empty($list_array))
echo "Array is empty";
else
echo "Array is not empty";
Your loop does not work because PHP arrays are zero based, you should start with zero and continue while $z < $arr_length
I found two errors in your code:
a parenthesis is not closed in Attempt 1
in your for cycle you are starting from 1 instead of starting from 0 (so, you are considering that the array will be something like array(1=>..., 2=>..., 3=>...), while it is actually array(0=>..., 1=>..., 2=>...)
So, here is your code, fixed:
$list_array = array();
$list_array[] = array (
'id' => 1,
'name' => 'Sean',
'codename' => 'Maverick'
);
$list_array[] = array (
'id' => 2,
'name' => 'Matt',
'codename' => 'Diesel'
);
$list_array[] = array (
'id' => 3,
'name' => 'Bonnie',
'codename' => 'Princess'
);
//Attempt 1:
if (empty($list_array))
echo "Array is empty";
//Attempt 2:
$arr_empty = true;
$arr_length = count($list_array);
echo "Length: " . $arr_length . "<br>";
for ($z=0; $z<$arr_length; $z++)
{
$arr_length2 = count($list_array[$z]);
echo $z . " Length2: " . $arr_length2 . "<br>";
if (empty($list_array[$z]))
echo $z . " Is Empty<br>";
}
You can try it here, with a simple copy and paste.
I am trying to display the details for the inner array below but don't know how. I manage to get the right answer but with a warning saying array to string conversion how do I avoid the warning along with the answer:
$user = array(
'name' => 'Joe Blogs',
'age' => 25,
'validate' => 'true',
'children' => array(
'Jack',
'Jill',
'Mark'
)
);
foreach($user as $v){
echo $v . ' ' ."<br />";
}
foreach($user['children'] as $h){
echo "$h ";
}
Your first loop will still try to echo the value of $user['children'], but arrays can't simply be echoed.... prevent the original loop from trying to display the child array, and leave that to your second loop
foreach($user as $v){
if (!is_array($v) {
echo $v . ' ' ."<br />";
}
}
or
foreach($user as $key => $v){
if ($key !== 'children') {
echo $v . ' ' ."<br />";
}
}
Can anyone help output a multidimensional array, please.
Not to sure where I have gone wrong.
The sort ordering looks correct, but its not displaying the results.
<?php
$atest = Array ( "0" => Array ( "id" => "913", "testname" => "qwerty1", "i" => "1" ),
"1" => Array ( "id" => "913", "testname" => "test22", "i" => "2" ),
"2" => Array ( "id" => "913", "testname" => "American1", "i" => "3" ),
"3" => Array ( "id" => "913", "testname" => "Eagle4", "i" => "4" ) );
$range = range('A','Z');
$output = array();
$output['#'] = array();
foreach($range as $letter){
$output[$letter] = array();
}
foreach($atest as $test){
if ($test["testname"] !='') {
$uc = ucfirst($test["testname"]);
if(array_search($uc[0], $range) === FALSE){
$output['#'][] = $uc;
} else {
$output[$uc[0]][] = $uc;
}
}
}
foreach($output AS $letter => $result){
echo $letter . "<br/>--------<br/>\n";
sort($result);
foreach($result AS $indresult){
echo '' . $indresult['testname'] . '<br/>';
}
echo "<br/>\n";
}
?>
You're not putting the whole sub-array into $output, you're only putting $uc. Change the middle foreach loop to:
foreach($atest as $test){
if ($test["testname"] !='') {
$uc = ucfirst($test["testname"]);
if(array_search($uc[0], $range) === FALSE){
$output['#'][] = $test;
} else {
$output[$uc[0]][] = $test;
}
}
}
Try to use print_r function, for example for array dump:
print_r($atest);
Try this
$output[$uc[0]][] = $test;
instead of
$output[$uc[0]][] = $uc; // only the name is stored.
See demo here
The sorting of array in alphabetical order is not outputting correctly.
It outputted as:
Demo
qwerty
Demo3
Test1
Test2
New1
Instead of:
Demo
Demo3
New1
qwerty
Test1
Test2
Code:
<?php
$dbresults= array ( "0" => array ( "id" => "1",
"cb_boutiquename1" => "Test1",
"cb_boutiquename2" => "Test2",
"cb_boutiquename3" => "New1"
),
"1" => array ( "id" => "2",
"cb_boutiquename1" => "Demo",
"cb_boutiquename2" => "qwerty",
"cb_boutiquename3" => "Demo3"
)
);
function sortarray($a, $b) {
return strcmp($a["cb_boutiquename$i"], $b["cb_boutiquename$i"]);
}
usort($dbresults, "sortarray");
while (list($key, $value) = each($dbresults)) {
$results[] = $value ;
}
foreach($results as $result) {
$i = 1;
while (array_key_exists("cb_boutiquename$i", $result)) {
if ($result["cb_boutiquename$i"] !='') {
echo '<a href=' . cbSef( 'index.php?option=com_comprofiler&task=page&user=' . (int) $result['id'] . '&b=' . $i . getCBprofileItemid( false )) . '>' . $result["cb_boutiquename$i"] . '</a><br />';
}
++$i;
}
}
?>
Your problem is that in here:
function sortarray($a, $b) {
return strcmp($a["cb_boutiquename$i"], $b["cb_boutiquename$i"]);
}
$i is undefined so you are basically comparing one undefined array offset with another.
If you want to specify which of the cb_boutiquename fields to specify at runtime then what you probably want to do is include the $i in the function, on php this can be done with a function that returns a closure (PHP 5.3+).
function getSorter($idx){
return function($a, $b) use ($idx) {
return strcmp($a["cb_boutiquename$idx"], $b["cb_boutiquename$idx"]);
};
}
This returns a function that closes over the supplied argument and is appropriate for use as a comparison function for usort. So for your sort call you would use:
usort($dbresults, getSorter(1));
Or for a more general solution that does not assume the cb_boutiquename prefix on the properties you can change this to
function getSorter($idx){
return function($a, $b) use ($idx) {
return strcmp($a[$idx], $b[$idx]);
};
}
usort($dbresults, getSorter("cb_boutiquename1"));
This will allow you to sort any array of arrays by an one of the indexes.
UPDATE
I completely misunderstood the goal of this exercise. What you want to do is to flatten your array prior to doing any sorting.
$dbresults= array ( "0" => array ( "id" => "1",
"cb_boutiquename1" => "Test1",
"cb_boutiquename2" => "Test2",
"cb_boutiquename3" => "New1"
),
"1" => array ( "id" => "2",
"cb_boutiquename1" => "Demo",
"cb_boutiquename2" => "qwerty",
"cb_boutiquename3" => "Demo3"
)
);
// flatten out the array
$results = array();
foreach($dbresults as $k=>$v){
foreach ($v as $key=>$value) {
if (substr($key, 0,15) == "cb_boutiquename"){
$results[] = array("id"=>$v["id"], "cb_boutiquename"=>$value, "i"=>substr($key, 15));
}
}
}
usort($results, function($a, $b){ return strcasecmp($a["cb_boutiquename"], $b["cb_boutiquename"]); });
foreach($results as $result){
echo '<a href=' . cbSef( 'index.php?option=com_comprofiler&task=page&user=' . (int) $result['id'] . '&b=' . $result["i"] . getCBprofileItemid( false )). '>' . $result["cb_boutiquename"] . '</a><br />'."\n";
}
Instead of your sortarray function, use simply this:
asort($dbresults);
No need to reinvent the wheel. Read about it here
I have a complex array, something like that:
Array {
k1 => text1
k2 => Array {
k3 =>text2
k4 => Array {
k5 => text3
}
k6 => text4
}
}
And i want to echo the array but to indent every subarray like this:
key: k1 >> value: text1
Array key: k2 >> values:
key: k3 >> value: text2
Array key: k4 >> values:
key: k5 >> value: text3
key: k6 >> value: text4
Let me know if you need any details.
Here's a recursive function that will indent:
(Edited: Indentation wasn't working properly for all subelements, now it does)
function arrayPrettyPrint($arr, $level = 0) {
foreach($arr as $k => $v) {
for($i = 0; $i < $level; $i++)
echo " "; // You can change how you indent here
if(!is_array($v))
echo($k . " => " . $v . "<br/>");
else {
echo($k . " => <br/>");
arrayPrettyPrint($v, $level+1);
}
}
}
$arr = array(
1, 2, 3,
array( 4, 5,
array( 6, 7, array( 8 )))
);
arrayPrettyPrint($arr);
It's print array like your.
<?php
function print_array($array, $tabs = '') {
$result = '';
if (is_array($array)) {
foreach ($array as $k => $v) {
if (is_array($v)) {
$result .= $tabs . 'Array key: '. $k . ' >> values: ' . PHP_EOL . print_array($v, $tabs."\t");
} else {
$result .= $tabs . 'key: ' . $k . ' value: ' . $v . PHP_EOL;
}
}
} else {
$result = $array . PHP_EOL;
}
return $result;
}
$array = array(
'k1' => 'text1',
'k2' => array(
'k3' => 'text2',
'k4' => array(
'k5' => 'text3'
),
'k6' => 'text4'
)
);
echo print_array($array);
?>
Try building on this quick function:
function recurseDisplay($my_array,$padding = 2){
echo "<br />";
foreach($my_array as $item){
if (is_array($item)){
$padding += 10;
for ($p = 0; $p < $padding; $p++){
echo " ";
}
echo "Array: {" ;
recurseDisplay($item,$padding);
echo " <br /> } <br />";
}
else{
for ($p = 0; $p < $padding; $p++){
echo " ";
}
echo "key :" . $item . "<br />";
}
}
}
recurseDisplay($my_array);
Would var_dump do the job for you?
myVar = Array {
k1 => text1
k2 => Array {
k3 =>text2
k4 => Array {
k5 => text3
}
k6 => text4
}
}
try it
var_dump(myVar)
It appears that this question was asked before here. This was the solution by KeithGrant
function RecursiveWrite($array) {
foreach ($array as $vals) {
echo "\t" . $vals['comment_content'];
RecursiveWrite($vals['child']);
}
}