Как «объединить» некоторые элементы массива в элемент одного и того же массива? - PullRequest
0 голосов
/ 30 сентября 2010
$foo = array(
    '1' => '2',
    '3' => array(
        '4' => '5'
    ),
    '6' => array(
        '7' => '8',
        '9' => '10',
        '11' => array(
            '12' => '13',
            '14' => '15'
        )
    )
);

$bar = array(
    '1',
    '6' => array(
        '7',
        '11' => array(
            '12'
        )
    )
);

Foo - это массив, который мне нужно отредактировать, исключить изменения, которые мне нужно сделать.

Мне нужно создать еще один элемент в массиве Foo, содержащий элементы, указанные в баре, и удалить оригиналы из Foo.

Итак, с массивом окончательный массив должен быть:

Array(
    '3' => array(
        '4' => '5'
    ),
    '6' => array(
        '9' => '10',
        '11' => array(
            '14' => '15'
        )
    ),
    'merged' => array(
        '1' => '2',
        '6' => array(
            '7' => '8',
            '11' => array(
                '12' => '13'
            )
        )
    )
)

Я построил эту рекурсивную функцию, но работает только для первого уровня массива:

foreach($bar AS $key => $value){
    if(is_array($value)){
        s($foo, $key, $value);
    }else{
        $foo['merged'][$value] = $foo[$value];
        unset($foo[$value]);
    }
}


function s(&$form, $key, $value){
    if(is_array($value)){
        foreach($value AS $k => $v){
            s($form, $k, $v);
        }
    }else{
        $form['merged'][$value] = $form[$value];
        unset($foo[$value]);
    }
}

Есть идеи?

1 Ответ

1 голос
/ 30 сентября 2010

Самая большая проблема с вашим сценарием на данный момент заключается в том, что вы предполагаете, что элемент без ключа является автономной конструкцией. Массив $ bar на самом деле выглядит так в PHP:

$bar = array(
    '0' => '1',
    '6' => array(
        '0' => '7',
        '11' => array(
            '0' => '12'
        )
    )
)

Понимая это, когда вы видите ключ '0' в $ bar, очевидно, что мы должны посмотреть на значение и переместить эту пару ключ => значение в $ foo ['merged'], но это становится более сложным, когда вы видите '6'. Еще сложнее, когда вы понимаете, что не можете просто вложить циклы foreach (), поскольку в этом массиве могут быть потенциально бесконечные уровни.

Хитрость в работе с произвольным числом уровней в любом абстрактном типе данных - это рекурсивная функция со статическим счетчиком (для отслеживания уровня). Таким образом, мы можем продолжать углубляться в $ bar, но вернемся туда, где мы остались, когда закончим. Если мы сделаем счетчик arary, мы можем отслеживать, как мы попали туда, где мы находимся. Таким образом, мы можем найти элемент в $ foo позже.

/* recursive_foobar is the only function you call */

function recursive_foobar(&$foo, $bar, &$merged){
    static $counter;
    if(is_empty($counter)){ // initialize counter the first time
        $counter = array();
    }
    foreach($bar as $key => $element){
        if(is_array($element)){
            $counter[] = $key;
            recursive_foobar($foo, $element, $merged[$key]);
        } else {
            $old_value = recursive_get($foo, array_push($counter, $element));
            recursive_remove($foo, array_push($counter, $element));
            array_merge($merged, $old_value);
        }
    }
    return $merged;
}

/* recursive_get returns a multi-level array containing the requested element at the lowest level */

function recursive_get($haystack, $key){
    static $return;
    if(count($key) > 1){
        $return[] = array(recursive_get($haystack[$key[0]], array_shift($key)));
    } else {
        $return[] = $haystack[$key[0]];
    }
    return $return;
}

/* recursive_remove will remove the requested element, leaving all containers untouched */

function recursive_remove(&$array, $key){
    if(count($key) > 1){
        recursive_remove($array[$key[0]], array_shift($key));
    } else {
        remove($array[$key[0]]) ???
    }
}

$foo['merged'] = array();
recursive_foobar($foo, $bar, $foo['merged']);

Это немного неаккуратно, но то, что вы просили, включало в себя довольно высокоуровневые конструкции и сложную логику. Возможно, есть несколько функций PHP, которые я не запомнил, которые могли бы сбрить немного кода, но вы говорите об удалении произвольных элементов из массивов произвольной длины с произвольной глубиной и произвольным числом раз ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...