0

i have array like below

array('1'=>'parent 1',
      '1.1'=>'1st child of 1',
      '1.2'=>'2nd child of 1',
      '2'=>'parent 2',
      '2.1'=>'1st child of 2',
      '2.2'=>'2nd child of 2',
      '3'=>'parent 3',
      '3.1'=>'1st child of 3',
      '3.2'=>'2nd child of 4'
    )

i need to find out array with parent value like below

 array('1'=>'parent 1',
       '2'=>'parent 2',
      '3'=>'parent 3',
        )

how i can use array filter here?

2
  • 2
    What do you have so far? Commented Jan 17, 2014 at 15:15
  • 1
    You can't use PHP's array_filter() function because that only filters on values, so have you tried a simple foreach() loop? Commented Jan 17, 2014 at 15:16

4 Answers 4

1

You'd probably be best to check for the existence of . inside the key, rather than the actual value of the numerous entries, in case the names are changed.

Unfortunately, PHP doesn't provide access to the array key inside an array_filter function. As such, you'd be better to use foreach() and check for the period using strpos():

function parentsOnly($arr)
{
    $retArr = array();

    foreach($arr as $key => $val)
    {
        if(strpos('.', $key) === false)
        {
             $retArr[$key] = $value;
        }
    }

    return $retArr;
}

You can then call the function and assign its result to the array. Something like this:

$parentArray = parentsOnly($array);
Sign up to request clarification or add additional context in comments.

Comments

0

its possible just a simple tweak

$arr=array('1'=>'parent 1',
      '1.1'=>'1st child of 1',
      '1.2'=>'2nd child of 1',
      '2'=>'parent 2',
      '2.1'=>'1st child of 2',
      '2.2'=>'2nd child of 2',
      '3'=>'parent 3',
      '3.1'=>'1st child of 3',
      '3.2'=>'2nd child of 4'
    );
$f = array_filter(array_keys($arr), function ($k){ return !strpos($k,"."); });
$filter = array_intersect_key($arr, array_flip($f));
print_r($filter);

output

Array ( [1] => parent 1 [2] => parent 2 [3] => parent 3 )

1 Comment

While it might work in your instance, the solution above could cause problems in other places. strpos($haystack,$needle) returns the first position of $needle inside $haystack, and false if it is not found. So, in this scenario $foo = "barbaz"; if(!strpos($foo,"bar")){ echo "Not Found"; } else { echo "Found"; } your output will be "Not Found" since strpos will return 0. You should always do a strict check on strpos $foo = "barbaz"; if(false === strpos($foo,"bar")){ echo "Not Found"; } else { echo "Found"; } that, will output "Found"
0

If there's no duplication in the array values, and they're all strings:

$result = array_flip(
    array_filter(
        array_flip($myArray),
        function ($value) {
            return strpos('.', $value === false);
        }
    )
);

Comments

0

If you are guaranteed unique values in the array, you could do array_flip to exchange the keys and values, and then array_filter, then array_flip again

$_a = array_flip($a);
$_a = array_filter($_a,function($val){
                         if(false === strpos($val,".")){
                           return true;
                         }
                         return false;
                   });
$a = array_flip($_a);

If not, you could use array_walk to null out the child values, then use array_filter. If null is a possible value for parents (or anything that resolves to false), then you can always choose your own to use for the children, and filter by that. If there isn't such a value you can use, this solution won't work.

$_a = $a;
array_walk($_a,function(&$val,$key){
                         if(false !== strpos($val,".")){
                           $val = null;
                         }
           });
$a = array_filter($_a);

You could also use array_keys, array_filter, and array_intersect_keys. This will work regardless of whether the values are unique, and, unlike the second solution, will work if a parent value is null.

$_a = array_keys($a);
$_a = array_filter($_a,function($val){
                         if(false === strpos($val,".")){
                           return true;
                         }
                         return false;
                   });
$_a = array_flip($_a); //1=>foo, 2=>bar becomes foo=>1, bar=>2
$a = array_intersect_keys($a,$_a);

I know it's often preferable to use array functions when possible, but I'm not sure if any of the above solutions is going to be better than a simple foreach:

$_a = [];
foreach($a as $k=>$v){
  if(false === strpos($k,".")){
    $_a[$k] = $v;
  }
}

However, your original question asked how to use array_filter, so I presented various options for utilizing it. As others have stated, though, if you need to filter based on the value of the key, there is no way to do that with JUST array_filter

1 Comment

Just a note, in my versions, I check if false === strpos, not just !strpos (or false == strpos).... It's good to use this form, because if the needle appears as the first character in the haystack, it strpos will return 0. I don't think it's possible, in your case, for the "." to be the first character, but, it doesn't hurt to do it the way I did, and once you are in the habit of doing it that way, you don't have to worry about doing it when it does matter.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.