키 이름 / 경로로 다차원 배열에 액세스하고 조작하는 방법?
PHP키 이름 / 경로로 다차원 배열에 액세스하고 조작하는 방법?
필자는 배열 (타겟)의 키 또는 하위 키를 지정하여 점 분리 키 값으로 이름을 전달하는 PHP에서 설정기를 구현해야합니다.
주어진 다음 코드 :
$arr = array('a' => 1,
'b' => array(
'y' => 2,
'x' => array('z' => 5, 'w' => 'abc')
),
'c' => null);
$key = 'b.x.z';
$path = explode('.', $key);
$ key의 값에서 $ arr [ 'b'] [ 'x'] [ 'z']의 값 5에 도달하고 싶습니다.
지금.... $ key의 변수 값과 다른 $ arr 값 (깊이가 다른)이 주어진다.
getter get ()에 대해이 코드를 작성했습니다.
public static function get($name, $default = null)
{
$setting_path = explode('.', $name);
$val = $this->settings;
foreach ($setting_path as $key) {
if(array_key_exists($key, $val)) {
$val = $val[$key];
} else {
$val = $default;
break;
}
}
return $val;
}
내가 올바른 요소 ($ 키에 있음)에 도달했기 때문에 setter를 작성하는 것이 더 어렵지만 원래 배열에서 값을 설정할 수 없으며 한 번에 키를 지정하는 방법을 알지 못합니다.
어떤 종류의 역 추적을 사용해야합니까? 아니면 피할 수 있습니까?
해결법
-
==============================
1.
$ path가 이미 explode (또는 함수에 추가)를 통해 배열이라고 가정하면 참조를 사용할 수 있습니다. 잘못된 $ 경로 등의 경우 오류 검사를 추가해야합니다 (isset 생각).
$key = 'b.x.z'; $path = explode('.', $key);
function get($path, $array) { //$path = explode('.', $path); //if needed $temp =& $array; foreach($path as $key) { $temp =& $temp[$key]; } return $temp; } $value = get($path, $arr); //returns NULL if the path doesn't exist
이 조합은 기존 배열에 값을 설정하거나 아직 정의되지 않은 배열을 전달하면 배열을 만듭니다. $ array를 참조 & $ array로 전달하도록 정의하십시오 :
function set($path, &$array=array(), $value=null) { //$path = explode('.', $path); //if needed $temp =& $array; foreach($path as $key) { $temp =& $temp[$key]; } $temp = $value; } set($path, $arr); //or set($path, $arr, 'some value');
이렇게하면 경로의 마지막 키가 설정 해제됩니다.
function unsetter($path, &$array) { //$path = explode('.', $path); //if needed $temp =& $array; foreach($path as $key) { if(!is_array($temp[$key])) { unset($temp[$key]); } else { $temp =& $temp[$key]; } } } unsetter($path, $arr);
* 원래 응답에는 누군가에게 유용 할 경우를 대비하여 내가 남길 몇 가지 제한된 기능이있었습니다.
세터
$ array를 참조 & $ array로 전달하도록 정의하십시오 :
function set(&$array, $path, $value) { //$path = explode('.', $path); //if needed $temp =& $array; foreach($path as $key) { $temp =& $temp[$key]; } $temp = $value; } set($arr, $path, 'some value');
또는 업데이트 된 배열을 반환하려는 경우 (지루해하기 때문에) :
function set($array, $path, $value) { //$path = explode('.', $path); //if needed $temp =& $array; foreach($path as $key) { $temp =& $temp[$key]; } $temp = $value; return $array; } $arr = set($arr, $path, 'some value');
창조자
배열을 생성하고 선택적으로 값을 설정하지 않으려면 다음을 수행하십시오.
function create($path, $value=null) { //$path = explode('.', $path); //if needed foreach(array_reverse($path) as $key) { $value = array($key => $value); } return $value; } $arr = create($path); //or $arr = create($path, 'some value');
재미있는
$ array [ 'b'] [ 'x'] [ 'z'];와 같은 것을 구성하고 평가합니다. 주어진 문자열 b.x.z :
function get($array, $path) { //$path = explode('.', $path); //if needed $path = "['" . implode("']['", $path) . "']"; eval("\$result = \$array{$path};"); return $result; }
-
==============================
2.
내가 당신을 위해 순수한 PHP가 아니라 솔루션을 OUZO 케이크를 구체적으로 사용하여 배열 :: getNestedValue 메서드 :
$arr = array('a' => 1, 'b' => array( 'y' => 2, 'x' => array('z' => 5, 'w' => 'abc') ), 'c' => null); $key = 'b.x.z'; $path = explode('.', $key); print_r(Arrays::getNestedValue($arr, $path));
마찬가지로 중첩 된 값을 설정해야하는 경우 Arrays :: setNestedValue 메서드를 사용할 수 있습니다.
$arr = array('a' => 1, 'b' => array( 'y' => 2, 'x' => array('z' => 5, 'w' => 'abc') ), 'c' => null); Arrays::setNestedValue($arr, array('d', 'e', 'f'), 'value'); print_r($arr);
-
==============================
3.
나는 내가 공유 할 유틸리티를 정기적으로 사용한다. 차이점은 점 표기법 (예 : b.x.z) 대신 배열 액세스 표기법 (예 : b [x] [z])을 사용한다는 것입니다. 문서와 코드를 사용하면 매우 자명합니다.
<?php class Utils { /** * Gets the value from input based on path. * Handles objects, arrays and scalars. Nesting can be mixed. * E.g.: $input->a->b->c = 'val' or $input['a']['b']['c'] = 'val' will * return "val" with path "a[b][c]". * @see Utils::arrayParsePath * @param mixed $input * @param string $path * @param mixed $default Optional default value to return on failure (null) * @return NULL|mixed NULL on failure, or the value on success (which may also be NULL) */ public static function getValueByPath($input,$path,$default=null) { if ( !(isset($input) && (static::isIterable($input) || is_scalar($input))) ) { return $default; // null already or we can't deal with this, return early } $pathArray = static::arrayParsePath($path); $last = &$input; foreach ( $pathArray as $key ) { if ( is_object($last) && property_exists($last,$key) ) { $last = &$last->$key; } else if ( (is_scalar($last) || is_array($last)) && isset($last[$key]) ) { $last = &$last[$key]; } else { return $default; } } return $last; } /** * Parses an array path like a[b][c] into a lookup array like array('a','b','c') * @param string $path * @return array */ public static function arrayParsePath($path) { preg_match_all('/\\[([^[]*)]/',$path,$matches); if ( isset($matches[1]) ) { $matches = $matches[1]; } else { $matches = array(); } preg_match('/^([^[]+)/',$path,$name); if ( isset($name[1]) ) { array_unshift($matches,$name[1]); } else { $matches = array(); } return $matches; } /** * Check if a value/object/something is iterable/traversable, * e.g. can it be run through a foreach? * Tests for a scalar array (is_array), an instance of Traversable, and * and instance of stdClass * @param mixed $value * @return boolean */ public static function isIterable($value) { return is_array($value) || $value instanceof Traversable || $value instanceof stdClass; } } $arr = array('a' => 1, 'b' => array( 'y' => 2, 'x' => array('z' => 5, 'w' => 'abc') ), 'c' => null); $key = 'b[x][z]'; var_dump(Utils::getValueByPath($arr,$key)); // int 5 ?>
-
==============================
4.
배열의 키가 고유하면 array_walk_recursive를 사용하여 몇 줄의 코드로 문제를 해결할 수 있습니다.
$arr = array('a' => 1, 'b' => array( 'y' => 2, 'x' => array('z' => 5, 'w' => 'abc') ), 'c' => null); function changeVal(&$v, $key, $mydata) { if($key == $mydata[0]) { $v = $mydata[1]; } } $key = 'z'; $value = '56'; array_walk_recursive($arr, 'changeVal', array($key, $value)); print_r($arr);
-
==============================
5.
"getter"로서, 나는 이것을 과거에 사용했습니다 :
$array = array('data' => array('one' => 'first', 'two' => 'second')); $key = 'data.one'; function find($key, $array) { $parts = explode('.', $key); foreach ($parts as $part) { $array = $array[$part]; } return $array; } $result = find($key, $array); var_dump($result);
-
==============================
6.
정말 간단하고 더러운 해결책이 있습니다 (정말 더럽습니다! 키 값이 신뢰할 수 없다면 사용하지 마십시오!). 배열을 반복하는 것보다 더 효율적일 수 있습니다.
function array_get($key, $array) { return eval('return $array["' . str_replace('.', '"]["', $key) . '"];'); } function array_set($key, &$array, $value=null) { eval('$array["' . str_replace('.', '"]["', $key) . '"] = $value;'); }
이 두 함수는 키가 배열의 요소로 PHP 코드로 변환되는 코드 스 니펫에 대한 평가를 수행합니다. 그리고 해당 키에 배열 값을 반환하거나 설정합니다.
-
==============================
7.
이 함수는 받아 들인 답과 같습니다만, 키가 존재하면 참 / 거짓으로 설정된 세 번째 매개 변수를 참조로 추가합니다
function drupal_array_get_nested_value(array &$array, array $parents, &$key_exists = NULL) { $ref = &$array; foreach ($parents as $parent) { if (is_array($ref) && array_key_exists($parent, $ref)) { $ref = &$ref[$parent]; } else { $key_exists = FALSE; $null = NULL; return $null; } } $key_exists = TRUE; return $ref; }
from https://stackoverflow.com/questions/27929875/how-to-access-and-manipulate-multi-dimensional-array-by-key-names-path by cc-by-sa and MIT lisence
'PHP' 카테고리의 다른 글
PHP 세션이 하위 도메인으로 이월되도록 허용 (0) | 2018.09.05 |
---|---|
어떻게 PHP에서 세션 시간 초과를 변경하려면? (0) | 2018.09.05 |
내 MySQLi 쿼리에 대한 오류를 표시하는 방법? [복제] (0) | 2018.09.05 |
URL에 대한 PHP 유효성 검사 / 정규식 (0) | 2018.09.05 |
PDO로 행 수 계산 (0) | 2018.09.05 |