2014-01-17 4 views
0

У меня есть массив, как показано нижемассива для фильтрации с помощью клавиши ДАННЫЕ

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' 
    ) 

мне нужно выяснить массив родительского значения, как показано ниже

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

, как я могу использовать фильтр массива здесь?

+2

Что у вас есть? – jeroen

+1

Вы не можете использовать функцию 'array_filter()' PHP, потому что она только фильтрует значения, так что вы пробовали простой цикл foreach()? –

ответ

0

его можно только простой твик

$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); 

выход

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

Хотя это может работать в вашем случае, решение выше может вызвать проблемы в других местах.'strpos ($ haystack, $ needle)' возвращает первую позицию $ needle внутри $ haystack и false, если она не найдена. Итак, в этом случае '$ foo =" barbaz "; if (! Strpos ($ foo, "bar")) { echo "Not Found"; } else { echo "Найдено"; } '} Ваш вывод будет« Not Found », поскольку strpos вернет 0. Вы должны всегда выполнять строгую проверку strpos ' $ foo = "barbaz"; if (false === strpos ($ foo, "bar")) { echo "Not Found"; } else { echo "Найдено"; } ', что будет выводить« Найдено » – chasepeeler

1

Возможно, вам лучше всего проверить наличие . внутри ключа, а не фактическое значение многочисленных записей, если имена изменены.

К сожалению, PHP не предоставляет доступ к ключу массива внутри функции array_filter. Таким образом, вы бы лучше использовать foreach() и проверить на период с использованием strpos():

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

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

    return $retArr; 
} 

Вы можете вызвать функцию и назначить ее результат в массив. Что-то вроде этого:

$parentArray = parentsOnly($array); 
0

Если нет дублирования значений массива, и они все строки:

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

Если вы являетесь гуаром anteed уникальных значений в массиве, вы могли бы сделать array_flip для обмена ключей и значений, а затем array_filter, затем array_flip снова

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

Если нет, то вы могли бы использовать array_walk обнулять дочерние значения, а затем использовать array_filter. Если null - это возможное значение для родителей (или что-либо, что разрешает false), вы всегда можете выбрать свой собственный для использования для детей и фильтровать по нему. Если такого значения вы не можете использовать, это решение не будет работать.

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

Вы также можете использовать array_keys, array_filter и array_intersect_keys. Это будет работать независимо от того, являются ли значения уникальными и, в отличие от второго решения, будет работать, если родительское значение равно 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); 

Я знаю, что часто предпочтительнее использовать функции массива, когда это возможно, но я не уверен, что если какой-либо из указанных выше решений будет лучше, чем просто Еогеасп:

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

Однако, ваш оригинальный вопрос спросил, как использовать array_filter, поэтому я представил различные варианты его использования. Как утверждали другие, однако, если вам нужно фильтровать на основе значения ключа, нет никакого способа сделать это с помощью JUST array_filter

+0

Просто примечание, в моих версиях, я проверяю, если false === strpos, а не просто! Strpos (или false == strpos) .... Полезно использовать эту форму , потому что если игла появляется как первый символ в стоге сена, то strpos вернет 0. Я не думаю, что в вашем случае это возможно для «.». быть первым персонажем, но это не помешает сделать это так, как я сделал, и как только вы привыкли делать это таким образом, вам не нужно беспокоиться об этом, когда это имеет значение. – chasepeeler

Смежные вопросы