За последние 24 часа нас посетили 30518 программистов и 1812 роботов. Сейчас ищут 895 программистов ...

Удаление пустых элементов многомерного массива

Тема в разделе "PHP для новичков", создана пользователем and, 7 фев 2017.

  1. and

    and Новичок

    С нами с:
    18 май 2015
    Сообщения:
    16
    Симпатии:
    0
    Народ помогите туплю уже пару часов,

    Есть:
    Двумерный массив - примере ниже. Количество элементов во всех массивах 2-го уровня всегда одинаково, т.е. может быть везде например по 5, ну и в массиве top все элементы всегда имеют значение.

    Нужно:
    Если элементы массива с одинаковым ключом пусты (кроме массива top соответственно. в примере ниже это элементы с ключом 0) то удалить все элементы с данным ключом во всех массивах 2-го уровня. Количество совпадающих по ключам пустых элементов может не быть, а могут быть пусты все

    Код (Text):
    1.  
    2. <?php
    3. $test = array(
    4.     "top" => array(
    5.         0 => "Значение",
    6.         1 => "Значение",
    7.         2 => "Значение"
    8.     ),
    9.     0 => array(
    10.         0 => "",
    11.         1 => "",
    12.         2 => "Значение"
    13.     ),
    14.     1 => array(
    15.         0 => "",
    16.         1 => "Значение",
    17.         2 => ""
    18.     ),
    19.     2 => array(
    20.         0 => "",
    21.         1 => "Значение",
    22.         2 => "Значение"
    23.     )
    24. );
    25. ?>
     
  2. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    ну выкладывай код как делал то и что конкретно не получается
     
  3. domio

    domio Активный пользователь

    С нами с:
    18 дек 2012
    Сообщения:
    35
    Симпатии:
    5
    PHP:
    1. $test = array(
    2.     "top" => array(
    3.         0 => "Значение",
    4.         1 => "Значение",
    5.         2 => "Значение"
    6.     ),
    7.     0 => array(
    8.         0 => "",
    9.         1 => "",
    10.         2 => "Значение"
    11.     ),
    12.     1 => array(
    13.         0 => "",
    14.         1 => "Значение",
    15.         2 => ""
    16.     ),
    17.     2 => array(
    18.         0 => "",
    19.         1 => "Значение",
    20.         2 => "Значение"
    21.     )
    22. );
    23. print_r($test);
    24.  
    25. foreach ($test as $mainKey=>$subArr) {
    26.     foreach ($subArr as $key=>$item) {
    27.         if($item == ""){
    28.             unset($test[$mainKey][$key]);
    29.         }
    30.     }
    31. }
    32. print_r($test);
    так?
     
  4. and

    and Новичок

    С нами с:
    18 май 2015
    Сообщения:
    16
    Симпатии:
    0
    Нет, в данном примере если
    test[0][0] && test[1][0] && test[2][0] == ""
    то
    unset($test['top'][0], test[0][0], test[1][0], test[2][0]);
     
  5. and

    and Новичок

    С нами с:
    18 май 2015
    Сообщения:
    16
    Симпатии:
    0
    Сделал ежик из костылей, может кто предложит получше вариант
    Код (Text):
    1.  
    2. <?php
    3. $test = array(
    4.     "top" => array(
    5.         0 => "Значение",
    6.         1 => "Значение",
    7.         2 => "Значение"
    8.     ),
    9.     0 => array(
    10.         0 => "",
    11.         1 => "",
    12.         2 => "Значение"
    13.     ),
    14.     1 => array(
    15.         0 => "",
    16.         1 => "",
    17.         2 => ""
    18.     ),
    19.     2 => array(
    20.         0 => "",
    21.         1 => "Значение",
    22.         2 => "Значение"
    23.     )
    24. );
    25.  
    26. $arr = $test;
    27. $c = count($arr['top']);
    28. unset($arr['top']);
    29. $empty = array();
    30. foreach($arr as $k1 => $arr2){
    31.     for($i=0; $i<$c; $i++){
    32.         if($arr2[$i] == ""){ $empty[$i]++; };
    33.         if($empty[$i] == $c){$arr_empty[$i] = 1;}
    34.     }
    35. }
    36. if(isset($arr_empty)){
    37.     foreach($test as $k1 => $v1){
    38.         foreach($arr_empty as $k2 => $v2){
    39.             if(isset($test['top'][$k2])) unset($test['top'][$k2]);
    40.             unset($test[$k1][$k2]);
    41.         }
    42.     }
    43. }
    44. echo '<pre>',print_r($test),'</pre>';
    45. ?>
    46. [code]
     
  6. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    @and а значения которые не пустые, они во всех массивах разные под одинаковыми ключами?
     
  7. and

    and Новичок

    С нами с:
    18 май 2015
    Сообщения:
    16
    Симпатии:
    0
  8. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    PHP:
    1. $test = array(
    2.     "top" => array(
    3.         0 => "Значение",
    4.         1 => "Значение",
    5.         2 => "Значение"
    6.     ),
    7.     0 => array(
    8.         0 => "",
    9.         1 => "Значение",
    10.         2 => "Значение"
    11.     ),
    12.     1 => array(
    13.         0 => "",
    14.         1 => "Значение",
    15.         2 => ""
    16.     ),
    17.     2 => array(
    18.         0 => "",
    19.         1 => "Значение",
    20.         2 => "Значение"
    21.     )
    22. );
    23.  
    24. $array = $test;
    25. unset($array['top']);
    26. $result = [];
    27. $need = count($array);
    28. for ($i = 0; $i < count($array[0]); $i++) {
    29.     $have = 0;
    30.     $tmp = $result;
    31.     foreach ($array as $k => $v) {
    32.         if ($v[$i] === "") {
    33.             continue;
    34.         }
    35.         $have++;
    36.         $tmp[$k][$i] = $v[$i];
    37.         if ($have == $need) {
    38.             $result = $tmp;
    39.         }
    40.     }
    41. }
    42. print_r($result);
    Результат:
    Код (Text):
    1. Array
    2. (
    3.     [0] => Array
    4.         (
    5.             [1] => Значение
    6.         )
    7.  
    8.     [1] => Array
    9.         (
    10.             [1] => Значение
    11.         )
    12.  
    13.     [2] => Array
    14.         (
    15.             [1] => Значение
    16.         )
    17.  
    18. )
     
  9. and

    and Новичок

    С нами с:
    18 май 2015
    Сообщения:
    16
    Симпатии:
    0
    Почти то, но в результате должно выводиться (результат ниже),
    то есть должны удаляться элементы только если они пусты во всех (кроме [top]) массивах 2-го уровня имеющих один ключ, и данный ключ должен удаляться из [top]
    Мое решение тоже не работает в случае увеличения количества элементов в массивах второго уровня, вроде несложная проблема, а времени уже кучу убил

    Код (Text):
    1. Array
    2. (
    3.     [top] => Array
    4.         (
    5.             [1] => Значение
    6.             [2] => Значение
    7.         )
    8.  
    9.     [0] => Array
    10.         (
    11.             [1] => Значение
    12.             [2] => Значение
    13.         )
    14.  
    15.     [1] => Array
    16.         (
    17.             [1] => Значение
    18.             [2] =>
    19.         )
    20.  
    21.     [2] => Array
    22.         (
    23.             [1] => Значение
    24.             [2] => Значение
    25.         )
    26.  
    27. )
     
  10. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.984
    Симпатии:
    759
    Добро пожаловать в офис мастера костылей и высоких нагрузок.

    PHP:
    1. $arrInp = array(
    2.     "top" => array(
    3.         0 => "Значение",
    4.         1 => "Значение",
    5.         2 => "Значение"
    6.     ),
    7.     0 => array(
    8.         0 => "",
    9.         1 => "",
    10.         2 => "Значение"
    11.     ),
    12.     1 => array(
    13.         0 => "",
    14.         1 => "Значение",
    15.         2 => ""
    16.     ),
    17.     2 => array(
    18.         0 => "",
    19.         1 => "Значение",
    20.         2 => "Значение"
    21.     )
    22. );
    23.  
    24. $wrcCntLv1 = count($arrInp) - 1;
    25.  
    26. $wrcCntLv2 = count($arrInp['top']);
    27.  
    28. $codeArr = array();
    29.  
    30. for ( $i = 0; $i < $wrcCntLv2; $i++ ) {
    31.  
    32. for ( $k = 0; $k < $wrcCntLv1; $++ ) {
    33.  
    34. $codeArr[] = "emty(\$arrInp[$k][$i])";
    35.  
    36. }
    37.  
    38. $code = "if (";
    39.  
    40. $LstItPos = count($codeArr) - 1;
    41.  
    42. for ( $z = 0; $z < count($codeArr); $z++ ) {
    43.  
    44. if ( $z == $LstItPos ) {
    45.  
    46. $code .= $codeArr[$z];
    47.  
    48. } else {
    49.  
    50. $code .= $codeArr[$z]." &&";
    51.  
    52. }
    53.  
    54. }
    55.  
    56. $code .= ") \{
    57.  
    58. foreach ( \$arrInp as \$key=>\$val ) \{
    59.  
    60. unset(\$arrInp[\$key][$i]);
    61.  
    62. \}
    63.  
    64. \}";
    65.  
    66. eval($code);
    67.  
    68. }
    Поржал от души, но должно работать.:D

    Комментировать и проверять нет времени. Надо бежать.

    Если не будет работать, то не пытайся разобраться. Я приду и отлажу сам.
    --- Добавлено ---
    это при условии:
     
  11. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.984
    Симпатии:
    759
    Ошибок было несколько синтаксических и логических.

    Вот новый отлаженный код:

    PHP:
    1. $arrInp = array(
    2.     "top" => array(
    3.         0 => "Значение",
    4.         1 => "Значение",
    5.         2 => "Значение"
    6.     ),
    7.     0 => array(
    8.         0 => "",
    9.         1 => "",
    10.         2 => "Значение"
    11.     ),
    12.     1 => array(
    13.         0 => "",
    14.         1 => "Значение",
    15.         2 => ""
    16.     ),
    17.     2 => array(
    18.         0 => "",
    19.         1 => "Значение",
    20.         2 => "Значение"
    21.     )
    22. );
    23.  
    24. $wrcCntLv1 = count($arrInp) - 1;
    25.  
    26. $wrcCntLv2 = count($arrInp['top']);
    27.  
    28. $codeArr = array();
    29.  
    30. for ( $i = 0; $i < $wrcCntLv2; $i++ ) {
    31.  
    32. for ( $k = 0; $k < $wrcCntLv1; $k++ ) {
    33.  
    34. $codeArr[] = " empty(\$arrInp[$k][$i])";
    35.  
    36. }
    37.  
    38. $code = "if (";
    39.  
    40. $LstItPos = count($codeArr) - 1;
    41.  
    42. for ( $z = 0; $z < count($codeArr); $z++ ) {
    43.  
    44. if ( $z == $LstItPos ) {
    45.  
    46. $code .= $codeArr[$z];
    47.  
    48. } else {
    49.  
    50. $code .= $codeArr[$z]." &&";
    51.  
    52. }
    53.  
    54. }
    55.  
    56. $code .= ") {
    57.  
    58. foreach ( \$arrInp as \$key=>\$val ) {
    59.  
    60. unset(\$arrInp[\$key][$i]);
    61.  
    62. }
    63.  
    64. }";
    65.  
    66.  
    67. eval($code);
    68.  
    69.  
    70. unset($codeArr);
    71.  
    72. }
     
  12. and

    and Новичок

    С нами с:
    18 май 2015
    Сообщения:
    16
    Симпатии:
    0
    здесь похоже без костылей не обойтись)))
    я уже тоже запустил, уж не знаю что лучше
    PHP:
    1. $test = array(
    2.     "top" => array(
    3.         0 => "top 0",
    4.         1 => "top 1",
    5.         2 => "top 2",
    6.         3 => "top 3",
    7.         4 => "top 4"
    8.     ),
    9.     0 => array(
    10.         0 => "",
    11.         1 => "",
    12.         2 => "Значение 0 2",
    13.         3 => "Значение 0 3",
    14.         4 => ""
    15.     ),
    16.     1 => array(
    17.         0 => "",
    18.         1 => "",
    19.         2 => "",
    20.         3 => "Значение 1 3",
    21.         4 => ""
    22.     ),
    23.     2 => array(
    24.         0 => "",
    25.         1 => "",
    26.         2 => "Значение 2 2",
    27.         3 => "Значение 2 3",
    28.         4 => ""
    29.     )
    30. );
    31. $arr = $test;
    32. unset($arr['top']);
    33. $arr_empty = array();
    34. $c = count($arr);
    35. // Вычисляем ключи у которых заначения = "" во всех массивах 2-го уровня
    36. for ($i = 0; $i < count($arr[0]); $i++) {
    37.     $empty = 0;
    38.     $tmp = $arr_empty;
    39.     foreach ($arr as $k => $v) {
    40.         if ($v[$i] !== "") continue;
    41.         $empty++;
    42.         $tmp[$i] = 1;
    43.         if ($empty == $c) $arr_empty = $tmp;
    44.     }
    45. }
    46. // Удаляем строку с пустыми значениями
    47. if(isset($arr_empty)){
    48.     foreach($test as $k1 => $v1){
    49.         foreach($arr_empty as $k2 => $v2){
    50.             if(isset($test['top'][$k2])) unset($test['top'][$k2]);
    51.             unset($test[$k1][$k2]);
    52.         }
    53.     }
    54. }
    55. echo '<pre>',print_r($test),'</pre>';
     
  13. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.984
    Симпатии:
    759
    @and я не стал вникать как работает твой вариант, но если он работает, то он точно лучше :)
     
  14. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Если ПХП, то всё проще.
    Как-то так:
    PHP:
    1. $test = array(
    2.         "top" => array(0 => "Значение",1 => "Значение",2 => "Значение"),
    3.         0 => array(0 => "",1 => "",2 => "Значение"),
    4.         1 => array(0 => "",1 => "Значение",2 => ""),
    5.         2 => array(0 => "",1 => "Значение",2 => "Значение")
    6.     );
    7.     $filter = [];
    8.     // Подсчёт количества
    9.     array_walk_recursive($test, function($v, $key) use(&$filter) { @$filter[$key] += (int)($v === ''); });
    10.     // условие: исключаемые должны быть у всех
    11.     $count = count($test) - 1; // условие: первый не учитывать
    12.     $filter = array_filter($filter, function($v) use($count) { return $v >= $count;});
    13.     // условие: удалить у всех
    14.     foreach($test as $k=>&$a) {
    15.         $a = array_filter($a, function($key) use($filter) { return !isset($filter[$key]); }, ARRAY_FILTER_USE_KEY);
    16.     }
    17.  
    18.     var_dump($test);
     
    mahmuzar нравится это.