Count number of times a string in mixed array php - php

I want an easy way to count a number of times the string "Apple" has present in the given
# My Array :
$arr = array(
1 => "Apple",
2 => "Orange",
3 => array(1=>"Bananna",2=>"Apple"),
4 => "Grape",
5 => "Apple",
6 => array(1=>"Grape"),
7 => "Orange");
# Want to count only "Apple"
$needle = "Apple";
# My Function :
function arrsearch($needle,$haystack,$return) {
if(!is_array($haystack)) {
return false;
}
foreach($haystack as $key=>$val) {
if(is_array($val)) {
$return = arrsearch($needle,$val,$return);
}else if(strtolower($val) == strtolower($needle)) {
$return[] = $key;
}
}
return $return;
}
$var = arrsearch("Apple",$arr,array());
echo " Output : ".count($var);
# Output : 3
I used the above function to find the number of times the string "Apple" in the array. Suggest me the best one.

You could use array_walk_recursive:
function search_for($arr, $term)
{
$count = 0;
array_walk_recursive($arr, function($item, $idx, $term) use (&$count) {
if (false !== stripos($item, $term)) {
++$count;
}
}, $term);
return $count;
}
search_for($arr, 'Apple'); // returns 3
The expression function($item, $idx, $term) use (&$count) { .. } is an anonymous function declaration; it works just like a regular function, but you can inherit variables from the parent scope by using use ($var) or use (&$var) if you need to modify it too. More examples can be found on the manual page.
Update
For versions of PHP < 5.3, you'd have to encapsulate the counter using objects:
class RecursiveArraySearcher
{
private $c = 0;
public static function find($arr, $term)
{
$obj = new self;
array_walk_recursive($arr, array($obj, 'ismatch'), $term);
return $obj->c;
}
public function ismatch($item, $key, $term)
{
if (false !== stripos($item, $term)) {
++$this->c;
}
}
}
echo RecursiveArraySearcher::find($arr, 'Apple'); // 3

You can use a recursive function like this ..
function finditem($item,$array){
$count = 0;
foreach($array as $key => $value){
if(is_array($value) == true){
$countx = finditem($item,$value);
$count = $count + $countx;
}else if($value == $item)
$count++;
}
return $count;
}
echo finditem("Apple",$arr);
Hope it helps.

Another solution is to flat the array and count the values:
<?php
function search_for($arr, $term) {
$flatten_array = array();
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
foreach($it as $v) {
$flatten_array[] = $v;
}
$count_values = array_count_values($flatten_array);
return $count_values[$term];
}
echo search_for($arr, 'Apple'); // print 3

Related

Accessing the nth element in multidimensional array

is there a simple way to access the nth element in a multidimensional array in php?
so for example
$arr = array(
[0] => array(1,4,7,3,53),
[6] => array(6,3,9,12,51,7),
[2] => array(9,94,54,3,87));
the 12th element would be 9.
array keys are not necessarily in order, nor each array row is of the same length.
Try this :
<?php
$arr = array(
'0'=> array(1,4,7,3,53),
'6'=>array(6,3,9,12,51,7),
'2'=>array(9,94,54,3,87)
);
$newArray=array();
foreach($arr as $array){
$newArray=array_merge($newArray, $array);
}
echo $newArray[11];
?>
untested, should work...
$arr = array(
0 => array(1,4,7,3,53), // your code was wrong here
6 => array(6,3,9,12,51,7),
2 => array(9,94,54,3,87));
function getnth ($array, $offset) {
$tmp_arr = array();
foreach ($array as $key => $value) {
foreach ($value as $val) {
$tmp_arr[] = $val;
}
}
return (isset($tmp_arr[$offset -1]) ? $tmp_arr[$offset -1] : FALSE);
}
getnth($arr, 12);
Edit: got to admit, the array_merge version is better....
Edit2: this is probably faster, if performance is an issue....
function getnth($array, $offset) {
$i = 0;
foreach ($array as $key => $value){
$size = count($value);
$i += $size;
if($offset <= $i) {
$new_off = $size - ($i - $offset) -1 ;
return $value[$new_off];
}
}
return FALSE;
}
function get_item($arr, $path, $delim = '.') {
$path = explode($delim, $path);
$result = $arr;
foreach ($path as $item) {
if (isset($result[$item])) {
$result = $result[$item];
} else {
return null;
}
}
return $result;
}
using:
echo get_item($arr, 'item.value.3.4.2.etc');

Comparing in_array values

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.

PHP - Mutidimensional array diff

i would like to ask for your help since I'm having difficulty resolving this matter. I had created a function to facilitate on array diff but it does not suffice to my needs. Thanks and more power!
<?php
$arraySession = array(
'sampleA' => array('1', '2', '3'),
'sampleB' => array('1', '2', '3'),
);
$arrayPost = array(
'sampleA' => array('1'),
'sampleB' => array('1','2'),
);
result should be:
array(
'sampleA' => array('2', '3')
'sampleB' => array('3'),
)
my existing function:
public function array_diff_multidimensional($session, $post) {
$result = array();
foreach($session as $sKey => $sValue){
foreach($post as $pKey => $pValue) {
if((string) $sKey == (string) $pKey) {
$result[$sKey] = array_diff($sValue, $pValue);
} else {
$result[$sKey] = $sValue;
}
}
}
return $result;
}
Any help would be much appreciated! Happy coding!
Not my function and not tested by me, but this was one of the first comments at php.net/array_diff (credit goes to thefrox at gmail dot com)
<?php
function multidimensional_array_diff($a1, $a2) {
$r = array();
foreach ($a2 as $key => $second) {
foreach ($a1 as $key => $first) {
if (isset($a2[$key])) {
foreach ($first as $first_value) {
foreach ($second as $second_value) {
if ($first_value == $second_value) {
$true = true;
break;
}
}
if (!isset($true)) {
$r[$key][] = $first_value;
}
unset($true);
}
} else {
$r[$key] = $first;
}
}
}
return $r;
}
?>
This should do it, assuming all keys occur in both arrays:
$diff = array();
foreach ($session as $key => $values) {
$diff[$key] = array_diff($values, $post[$key]);
}
Or, because I'm bored and array_map is underused:
$diff = array_combine(
array_keys($session),
array_map(function ($a, $b) { return array_diff($a, $b); }, $session, $post)
);
(Assumed well ordered arrays though.)
You want something more or less like this:
public function array_diff_multidimensional($arr1, $arr2) {
$answer = array();
foreach($arr1 as $k1 => $v1) {
// is the key present in the second array?
if (!array_key_exists($k1, $arr2)) {
$answer[$k1] = $v1;
continue;
}
// PHP makes all arrays into string "Array", so if both items
// are arrays, recursively test them before the string check
if (is_array($v1) && is_array($arr2[$k1])) {
$answer[$k1] = array_diff_multidimensional($v1, $arr2[$k1]);
continue;
}
// do the array_diff string check
if ((string)$arr1[$k1] === (string)$arr2[$k1]) {
continue;
}
// since both values are not arrays, and they don't match,
// simply add the $arr1 value to match the behavior of array_diff
// in the PHP core
$answer[$k1] = $v1;
}
// done!
return $answer;
}

PHP Search multidimensional associative array by key and return key => value

Hi i have a multidimensional associative array:
$array= array(
'Book1' => array('http://www.google.com', '45' ),
'Book2' => array('http://www.yahoo.com', '46', )
)
I need to be able to search $array on 'BookX' and then return the contents of 'BookX'.
Ive tried:
function array_searcher($needles, $array)
{
foreach ($needles as $needle) {
foreach ($array as $key )
{
if ($key == $needle)
{
echo $key;
}
}
}
}
with the search
$needles = array('Book1' , 'Book2' );
But this doesnt return anything
I might be misunderstanding, but this just sounds like the accessor. If not, could you clarify?
$array= array(
'Book1' => array('http://www.google.com', '45' ),
'Book2' => array('http://www.yahoo.com', '46', )
);
echo $array['Book1'];
EDIT: I did misunderstand your goal. I do have a comment on doing the two foreach loops. While this does work, when you have a very large haystack array, performance suffers. I would recommend using isset() for testing if a needle exists in the haystack array.
I modified the function to return an array of the found results to remove any performance hits from outputing to stdout. I ran the following performance test and while it might not do the same search over and over, it points out the inefficiency of doing two foreach loops when your array(s) are large:
function array_searcher($needles, $array) {
$result = array();
foreach ($needles as $needle) {
foreach ($array as $key => $value) {
if ($key == $needle) {
$result[$key] = $value;
}
}
}
return $result;
}
function array_searcher2($needles, $array) {
$result = array();
foreach ($needles as $needle) {
if (isset($array[$needle])) {
$result[$needle] = $array[$needle];
}
}
return $result;
}
// generate large haystack array
$array = array();
for($i = 1; $i < 10000; $i++){
$array['Book'.$i] = array('http://www.google.com', $i+20);
}
$needles = array('Book1', 'Book2');
$start = microtime(true);
for ($i = 0; $i < 1000; $i++) {
array_searcher($needles, $array);
}
echo (microtime(true) - $start)."\n";
// 14.2093660831
$start = microtime(true);
for ($i = 0; $i < 1000; $i++) {
array_searcher2($needles, $array);
}
echo (microtime(true) - $start)."\n";
// 0.00858187675476
If you want to search using the keys, you should access it as a key => value pair.
If you don't it only retrieves the value.
function array_searcher($needles, $array)
{
foreach ($needles as $needle)
{
foreach ($array as $key => $value)
{
if ($key == $needle)
{
echo $key;
}
}
}
}

Remove Parent in PHP Multidimensional Array

What's the best way to remove the parent of a matched key in an Multidimensional Array? For example, let's assume we have the following array and I want to find "[text] = a" and then delete its parent array [0]...
(array) Array
(
[0] => Array
(
[text] => a
[height] => 30
)
[1] => Array
(
[text] => k
[height] => 30
)
)
Here’s the obvious:
foreach ($array as $key => $item) {
if ($item['text'] === 'a') {
unset($array[$key]);
}
}
using array_filter:
function filter_callback($v) {
return !isset($v['text']) || $v['text'] !== 'a';
}
$array = array_filter($array, 'filter_callback');
this will only leave 'parent elements' in the array where text != a, therefore deleting those where text equals a
The inner arrays don't maintain any reference to their "parent" arrays, so you'd have to write a function to manually track this. Something like this might work:
function searchAndDestroy(&$arr, $needle) {
foreach ($arr as &$item) {
if (is_array($item)) {
if (searchAndDestroy($item, $needle)) {
return true;
}
} else if ($item === $needle) {
$item = null;
return true;
}
}
}
Note that this is designed to work at any level of nesting, not just two dimensions, so it might be a bit of overkill if you only need it for situations like in your example.
A simple and safe solution(I'd not remove/unset elements from an array I'm looping through) could be:
$new_array = array();
foreach($array as $item)
{
if($item['text'] != "a")
{
$new_array[] = $item;
}
}
My implementation:
function searchAndDestroy(&$a, $key, $val){
foreach($a as $k => &$v){
if(is_array($v)){
$r = searchAndDestroy(&$v, $key, $val);
if($r){
unset($a[$k]);
}
}elseif($key == $k && $val == $v){
return true;
}
}
return false;
}
searchAndDestroy($arr, 'text', 'a');
To test it:
<pre><?php
function searchAndDestroy(&$a, $key, $val){
foreach($a as $k => &$v){
if(is_array($v)){
$r = searchAndDestroy(&$v, $key, $val);
if($r){
unset($a[$k]);
}
}elseif($key == $k && $val == $v){
return true;
}
}
return false;
}
$arr = array(array('text'=>'a','height'=>'30'),array('text'=>'k','height'=>array('text'=>'a','height'=>'20')));
var_dump($arr);
searchAndDestroy($arr, 'text', 'a');
var_dump($arr);
?></pre>
This function does it recursively.

Categories