I'm using array_filter with multiple parameters but it's not doing the filter correctly. Here where it's supposed to return an array with only "arts,crafts,designs" as an element, it's returning an empty array. The only $askedcat parameter it works for is "arts". I can't find out what the issue is.
I've tried not using an array_filter and instead just looping over the array, and I get the same problem.
<?php
class CategoryFilter {
public $categoryAskedFor;
function __construct($askedCat) {
$this->categoryAskedFor = $askedCat;
}
function categoryCallback($projectCategoryString) {
$project_category_array = explode(",", $projectCategoryString);
if(in_array($this->categoryAskedFor, $project_category_array)) return true;
return false;
}
}
$verifiedProjects = ["arts", "arts,crafts,designs", "film", "film,theater"];
$askedCat = "crafts";
$newArr = array_filter($verifiedProjects, array(new CategoryFilter($askedCat), "categoryCallback"));
for ($i = 0; $i < count($newArr); $i++) {
echo $newArr[$i] . "<br>";
}
I expect the output here to be arts,crafts,design<br> but it's only <br> meaning the array is empty.
There are many way to achieve this but let me show you two way here
WAY #1
If you using the for loop to retrieve the array value then need to have numeric key and as per your code you need array_values function to manage that
<?php
class CategoryFilter {
public $categoryAskedFor;
function __construct($askedCat) {
$this->categoryAskedFor = $askedCat;
}
function categoryCallback($projectCategoryString) {
$project_category_array = explode(",", $projectCategoryString);
if(in_array($this->categoryAskedFor, $project_category_array)) return true;
return false;
}
}
$verifiedProjects = ["arts", "arts,crafts,designs", "film", "film,theater"];
$askedCat = "crafts";
$newArr = array_filter($verifiedProjects, array(new CategoryFilter($askedCat), "categoryCallback"));
$newArr = array_values($newArr);
for ($i = 0; $i < count($newArr); $i++) {
echo $newArr[$i] . "<br>";
}
WAY # 2
If you don't want to use the array_values here then you need to manage the foreach loop instead of for loop
<?php
class CategoryFilter {
public $categoryAskedFor;
function __construct($askedCat) {
$this->categoryAskedFor = $askedCat;
}
function categoryCallback($projectCategoryString) {
$project_category_array = explode(",", $projectCategoryString);
if(in_array($this->categoryAskedFor, $project_category_array)) return true;
return false;
}
}
$verifiedProjects = ["arts", "arts,crafts,designs", "film", "film,theater"];
$askedCat = "crafts";
$newArr = array_filter($verifiedProjects, array(new CategoryFilter($askedCat), "categoryCallback"));
foreach ($newArr as $value) {
echo $value . "<br>";
}
The way you're looping over your resulting array is wrong, because array_filter will preserve the array keys. The 0 index may not be there in the filtered version (and in your case, it actually isn't).
Use foreach instead:
foreach ($newArr as $value) {
echo $value, '<br>';
}
array_filter will remove elements but will not reset the keys. use array_values to reset the keys first.
$newArr = array_values($newArr);
for ($i = 0; $i < count($newArr); $i++) {
echo $newArr[$i] . "<br>";
}
You will get as per your output
$askedCat = 'crafts';
$verifiedProjects = ["arts", "arts,crafts,designs", "film", "film,theater"];
$newArr = array_filter($verifiedProjects, function ($item) use ($askedCat) {
if (stripos($item, $askedCat) !== false) {
return true;
}
return false;
});
foreach ($newArr as $value) {
echo $value . "<br>";
}
Related
I have an array, say
$updates = array();
$updates['U1'] = array('F1', 'F2', 'F5');
$updates['U2'] = array('F3');
$updates['U3'] = array('F3', 'F4');
I need search for a value say F5 so it should return the key U1.
And also if there is multiple occurrence of a value, should return the last key.
Eg. searching F3 should return U3 and not U2.
I have searched a lot and can't find a way. I am looking for a solution without using loops.
without using loop:
function findArrVal($arr = [], $param){
static $indx = 0;
if($indx == 0){
krsort($arr);
}
$keys = array_keys($arr);
$values = array_values($arr);
if( count($values) == $indx ){
return false;
} else if( is_array($values[$indx]) && in_array($param, $values[$indx])){
return $keys[$indx];
} else {
++$indx;
return findArrVal($arr, $param);
}
return FALSE;
}
using loop:
function findArrVal($arr = [], $param){
krsort($arr);
foreach($arr as $key => $ar){
if(is_array($ar) && in_array($param, $ar)){
return $key;
}
}
return FALSE;
}
findArrVal($updates,'F3');
krsort - sorts the array in reverse order. ( to find the value at first occurrence )
is_array to check if the child value is an array type.
in_array to find the item on the child array.
Maybe It's helpful for you.
function _getFindArrayKey(array $arr, $key)
{
if (array_key_exists($key, $arr)) {
return true;
}
// check arrays contained in this array
foreach ($arr as $element) {
if (is_array($element)) {
if (_getFindArrayKey($element, $key)) {
return true;
}
}
}
return false;
}
I want to get values using multiple keys.
I have a php code that works for single key but i want to get values for multiple keys. How can i do that?
<?php
$arr=array(
'1'=>'India',
'2'=>'Canada',
'3'=>'United',
'4'=>'China',
'5'=>'London',
'6'=>'New Delhi',
);
$key1='4';
$key2='3';
$key3='4';
echo $arr[$key1, $key2, $key3];
?>
I want output like this in proper order
China
United
China
Thanks in advance.
We have interface ArrayAccess in PHP:
https://www.php.net/manual/en/class.arrayaccess.php
So we can write code as following to support multiple keys( Updated the example from above page ):
You will have to update it to fit your requirements.
<?php
class MultipleKeyArray implements ArrayAccess {
private $container = array();
private $separator = ',';
public function __construct($arr ) {
$this->container = $arr;
}
public function setSeparator($str){
$this->separator = $str;
}
public function offsetSet($offsets, $values) {
$os = explode(',',$offsets);
$vs = explode(',',$values);
$max = max(count($os),count($vs));
for($i=0;$i<$max;$i++){
$offset = $os[$i];
$value = $vs[$i];
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
}
public function offsetExists($offsets) {
$os = explode(',',$offsets);
for($i=0;$i<count($os);$i++){
$offset = $os[$i];
if( !isset($this->container[$offset]) ){
return false;
}
}
return true;
}
public function offsetUnset($offsets) {
$os = explode(',',$offsets);
for($i=0;$i<count($os);$i++){
$offset = $os[$i];
unset($this->container[$offset]);
}
}
public function offsetGet($offsets) {
$os = explode(',',$offsets);
$result = '';
for($i=0;$i<count($os);$i++){
$offset = $os[$i];
$result .= ($i>0 ? $this->separator:'') . (isset($this->container[$offset]) ? $this->container[$offset] : '');
}
return $result;
}
}
$arr=array(
'1'=>'India',
'2'=>'Canada',
'3'=>'United',
'4'=>'China',
'5'=>'London',
'6'=>'New Delhi',
);
$o = new MultipleKeyArray($arr);
$o[] = 'new0';
$o['f,g']='new1,new2';
var_dump(isset($o['f,g']));
var_dump(isset($o['1,2,f']));
var_dump(isset($o['f,not,there']));
echo $o['4,3,4']."\n";
echo $o['2,f,g']."\n";
$o->setSeparator("|");
echo $o['4,3,4']."\n";
Output:
bool(true)
bool(true)
bool(false)
China,United,China
Canada,new1,new2
China|United|China
PHP index cannot take array - you should do that with loop or PHP array function.
First define array of the key you need as:
$keys = [$key1, $key2, $key3];
Now use a foreach loop to echo them as:
foreach($keys as $k)
echo $arr[$k] . PHP_EOL;
And the one-liner:
array_walk($keys, function($k) use ($arr) {echo $arr[$k] . PHP_EOL;});
The following code uses foreach on an array and if the value is an array it does a for each on the nested array
foreach ($playfull as $a)
{
if (is_array($a))
{
foreach ($a as $b)
{
print($b);
print("<p>");
}
} else {
print($a);
print("<p>");
}
}
This only works if you know that the arrays may only be nested one level deep
If arrays could be nested an unknown number of levels deep how do you achieve the same result? (The desired result being to print the value of every key in every array no matter how deeply nested they are)
You can use array_walk_recursive. Example:
array_walk_recursive($array, function (&$val)
{
print($val);
}
This function is a PHP built in function and it is short.
Use recursive functions (that are functions calling themselves):
function print_array_recursively($a)
{
foreach ($a as $el)
{
if (is_array($el))
{
print_array_recursively($el);
}
else
{
print($el);
}
}
}
This is the way, print_r could do it (see comments).
You want to use recursion, you want to call your printing function in itself, whenever you find an array, click here to see an example
$myArray = array(
"foo",
"bar",
"children" => array(
"biz",
"baz"),
"grandchildren" => array(
"bang" => array(
"pow",
"wow")));
function print_array($playfull)
{
foreach ($playfull as $a)
{
if (is_array($a))
{
print_array($a);
} else {
echo $a;
echo "<p>";
}
}
}
echo "Print Array\n";
print_array($myArray);
You could use a recursive function, but the max depth will be determined by the maximum nesting limit (see this SO question, Increasing nesting functions calls limit, for details about increasing that if you need it)
Here's an example:
$array = array(1,array(2,3,array(4,5)),6,7,8);
function printArray($item)
{
foreach ($item as $a)
{
if (is_array($a))
{
printArray($a);
} else {
print($a);
print("<p>");
}
}
}
printArray($array);
I hope that helps.
Try this -
function array_iterate($arr, $level=0, $maxLevel=0)
{
if (is_array($arr))
{
// unnecessary for this conditional to enclose
// the foreach loop
if ($maxLevel < ++$level)
{ $maxLevel = $level; }
foreach($arr AS $k => $v)
{
// for this to work, the result must be stored
// back into $maxLevel
// FOR TESTING ONLY:
echo("<br>|k=$k|v=$v|level=$level|maxLevel=$maxLevel|");
$maxLevel= array_iterate($v, $level, $maxLevel);
}
$level--;
}
// the conditional that was here caused all kinds
// of problems. so i got rid of it
return($maxLevel);
}
$array[] = 'hi';
$array[] = 'there';
$array[] = 'how';
$array['blobone'][] = 'how';
$array['blobone'][] = 'are';
$array['blobone'][] = 'you';
$array[] = 'this';
$array['this'][] = 'is';
$array['this']['is'][] = 'five';
$array['this']['is']['five'][] = 'levels';
$array['this']['is']['five']['levels'] = 'deep';
$array[] = 'the';
$array[] = 'here';
$var = array_iterate($array);
echo("<br><br><pre>$var");
I have a range of values in an array like:
$values = array(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.1,1.2,1.3,1.4,1.5);
I need to find the index of the smallest value in that array that's greater than or equal to a specified number. For example, if the user inputs 0.25, I need to know that the first array index is 2.
In other languages I've used, like R, there is a 'which' function that will return an array of indices that meet some criteria. I've not found that in PHP, so i'm hopeful someone else has solved this.
Thanks.
You can use array_filter
It does exactly what R which does.
Hope this function will help you,
function find_closest_item($array, $number) {
sort($array);
foreach ($array as $a) {
if ($a >= $number) return $a;
}
return end($array); // or return NULL;
}
I don't know if there's a built in function for that, but this should work:
function getClosest($input, $array)
{
foreach($array as $value)
{
if ($value >= $input)
{
return $value;
}
}
return false;
}
You can use the following working logic. There might be other built in functions which can be used to solve this problem.
<?php
$values = array(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.1,1.2,1.3,1.4,1.5);
$search=0.35;
$result_index = NULL;
$result_value=NULL;
$count=count($values);
for($i=0;$i<$count;$i++) {
if($values[$i]<$search) {
continue;
}
if($result_index==NULL) {
$result_index = $i;
$result_value = $values[$i];
continue;
}
if($values[$i]<$result_value) {
$result_index = $i;
$result_value = $values[$i];
}
}
print $result_index . " " . $result_value;
?>
You can build your own custom function:
function findIndex($input_array, $num)
{
foreach($input_array as $k => $v)
{
if($v >= $num)
{
return $k;
}
}
return false;
}
This function will return array index (key). If you don't want index, but the value, then other functions posted here will do the job. You should clarify what exactly you want to get as your question is a little bit amiguous
I have this function, which iterates through an array of objects in search of matching key => value pairs. I'm curious if there isn't an easier (or more graceful) way:
function count_class_attr($objects, $obj_key, $obj_val) {
$count = 0;
foreach ($objects as $object ) {
foreach ($object as $key => $value) {
if ($key == $obj_key && $value == $obj_val){
$count ++;
}
}
}
return $count;
}
I think below is closer to what I was looking for. I was looping through an array of objects, not an array of arrays - would the function below be as efficient as possible?
function count_class_attr($objects, $obj_key, $obj_val) {
$count = 0;
foreach ($objects as $object ) {
if (property_exists($object, $obj_key)) {
if($object->$obj_key == $obj_val) { $count ++; }
}
}
return $count;
}
Rather than iterating through the $object array, since this is a hash, a simple check if the key/value exists/matches should work, i.e.:
if (array_key_exists($obj_key, $object)) {
if ($object[$obj_key] == $obj_val) {
$count++
}
}
if (in_array($obj_key, array_keys($objects, $obj_val))
$count++;