Страницы

Поиск по вопросам

среда, 25 декабря 2019 г.

Как улучшить код по получению непустого элемента из массива?

#php


Вводные: есть некий массив с ключами, есть строка с несколькими ключами, один из
которых подойдет к этому массиву (т.е. элемент с таким ключом будет существовать).

Задача минимум: наиболее красиво получить значение первого элемента массива, ключ
которого подойдет.

Задача максимум: наиболее красиво получить значение первого элемента массива, ключ
которого подойдет, а если подойдут несколько ключей, выдать ошибку.

Задача сверх максимума: наиболее красиво получить значение первого элемента массива,
ключ которого подойдет, а если подойдут несколько ключей, выдать ошибку. При этом,
если ключ передан как fields[name_1], нужно понять, что имеется ввиду вложенность в
элемент и обработать очередной элемент массива в соответствии с этим.

На данный момент реализована задача минимум, но без красоты, на мой взгляд. Вот код:

function get_non_zero( $str_keys, $data ) {
    $keys = explode( ',', $str_keys );
    foreach ( $keys as $key ) {
        if ( ! empty( $data[ $key ] ) ) {
            return $data[ $key ];
        }
    }

    return null;
}

$data = ['key0' => 0, 'key1' => 1, 'key3'=> 3];
echo( get_non_zero( 'key1,key2', $data ) ); // выведет 1


Может быть, у кого-то есть идеи, как это реализовать более понятно и красиво, возможно,
вообще без функции?
    


Ответы

Ответ 1



Если пишите для себя, то можно так: $data = ["key0" => 0, "key1" => 1, "key3"=> 3]; $search = array_flip(explode(",", "key1,key2")); $result = array_intersect_key($data, $search); echo count($result) > 1 ? null : array_pop($result); Если с кодом будут работать и другие, тогда лучше в функцию, с комментариями и красивым ветвлением. function getNonZero($keys, $data) { $search = array_flip(explode(",", $keys)); $result = array_intersect_key($data, $search); if (count($result) > 1): return null; else: return array_pop($result); endif; } $data = ["key0" => 0, "key1" => 1, "key3"=> 3]; $search = "key1,key2"; echo getNonZero($search, $data); "Сверх максимум": function searchInArray($value) { preg_match("([\w+]{1,})", $value, $matches); return !empty($matches) ? $matches[0] : $value; } function getNonZero($search, $data) { $search = array_map("searchInArray", explode(",", $search)); $result = array_intersect_key($data, array_flip($search)); if (count($result) === 1): return is_array($result) ? array_shift($result[key($result)]) : $result; else: return null; endif; } $data = ['key0' => 0, 'fields' => ['name_1'=>1], 'key3'=> 3]; $sting = 'name,entry.436917433,billing_first_name,fields[name_1]'; echo getNonZero($sting, $data);

Ответ 2



В общем-то, достаточно элегантный вариант решения самой сложной задачи предложил в предыдущем ответе @socode, но после у меня возникла задача обрабатывать не только приведенные варианты в посте, типа fields[name_1], но и с большим количеством уровней вложенности. В этом случае, на мой взгляд, обязательно понадобится рекурсия, и можно равно как переписать вариант в другом ответе под это дело, так и написать другой: function preg_req( $key, &$keys = array() ) { preg_match( '/(.*)\[(.*)\]/', $key, $matches ); if ( count( $matches ) ) { $keys[] = $matches[2]; preg_req( $matches[1], $keys ); } else { $keys[] = $key; return $keys; } } function get_non_zero( $str_keys, $data ) { $keys = explode( ',', $str_keys ); foreach ( $keys as $key ) { $matched_keys = array(); preg_req( $key, $matched_keys ); $val = array_reduce( array_reverse($matched_keys), function ( $data, $key ) { return isset( $data[ $key ] ) ? $data[ $key ] : null; }, $data ); if ( ! empty( $val ) ) { return $val; } } return null; } $data['fields']['name_1'] = 'asdasd'; $data['fields']['1588698_1']['3762726'] = 'asdasd'; echo get_non_zero( 'name,billing,fields[name_1]', $data ); echo get_non_zero( 'phone,entry.3221,fields[1588698_1][3762726]', $data );

Комментариев нет:

Отправить комментарий