как получить доступ к позиции массива из строки

#php

Вопрос:

У меня есть строка, содержащая позицию ключа массива, которую я пытаюсь использовать для доступа к массиву ($arr).

Пример строки ($str), которая имеет строковое значение svg.1.linearGradient.0.@style

Это было бы эквивалентно ['svg'][1]['linearGradient'][0]['@style']

Как я могу использовать строку для доступа/извлечения данных из $arr, используя указанную выше позицию?

Например, допустим, я хотел сбросить ключ массива unset($arr['svg'][1]['linearGradient'][0]['@style']) — как я могу добиться этого программно?

Ответ №1:

Вы можете использовать механизм передачи значения по ссылке:

 $result = amp;$arr;
$path = explode('.', $str);

for($i = 0; $i < count($path); $i  ) {
    $key = $path[$i];
    if (is_array($result) amp;amp; array_key_exists($key, $result)) {
        if ($i == count($path) - 1) {
            unset($result[$key]); // deleting an element with the last key 
        } else {
            $result = amp;$result[$key];
        }
    } else {
        break; // not found
    }
}

unset($result); // resetting value by reference

print_r($arr);
 

играть на скрипке

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

1. это выглядит великолепно, спасибо!

2. есть ли способ получить исходное значение ключа с помощью этого также, если я хочу установить новый ключ с тем же значением ?

3. Если вам нужно сохранить значение перед его удалением, просто сохраните его в другой переменной. Если вам нужно заменить значение, просто назначьте новое, а не отменяйте $result[$key] = 'new value'; его . обновленная скрипка

4. я был бы признателен, если бы вы могли обновить скрипку, чтобы показать третий вариант и установить значение $result[$key] под новым именем ключа в той же позиции массива (давайте назовем это @style2) $arr['svg'][1]['linearGradient'][0][@style2] .. если, конечно, нет другого способа просто заменить существующее имя ключа? Я бы посмотрел на установку нового ключа со значением, предшествующим сбросу старого ключа

5. играть на скрипке

Ответ №2:

Одним из методов может быть разделение строки . , а затем повторение «ключей» для обхода вашего $arr объекта. (Пожалуйста, извините мой бедный php, прошло много времени…)

Пример:

 $arr = (object)[
    "svg" => (array)[
        (object)[],
        (object)[
            "linearGradient" => [
                (object)[
                    "@style" => "testing",
                ],
            ],
        ],
    ],
];

$str = "svg.1.linearGradient.0.@style";
$keys = explode('.', $str);
$val = $arr;
foreach($keys as $key) {
  $val =  is_object($val) 
    ? $val->$key 
    : $val[$key];
}

echo $val;
 

https://3v4l.org/h8YPv

Сброс ключа с учетом пути:

 $arr = (object)[
    "svg" => (array)[
        (object)[],
        (object)[
            "linearGradient" => [
                (object)[
                    "@style" => "testing",
                ],
            ],
        ],
    ],
];

$str = "svg.1.linearGradient.0.@style";
$keys = explode('.', $str);
$exp = "$arr";
$val = $arr;
foreach($keys as $index => $key) {
    $exp .=  is_object($val) 
        ? "->{'" . $key . "'}"
        : "[" . $key . "]";
    
    $val = is_object($val) ? $val->$key : $val[$key]; 
}

eval("unset($exp);");
 

https://3v4l.org/Fdo6B

Документы

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

1. спасибо, это позволяет мне получить доступ к массиву и вернуть значение. Что, если я захочу отключить ключ и его значение? unset($arr['svg'][1]['linearGradient'][0]['@style']) ?

2. да, но фрагмент кода возвращает только пару «ключ» и «значение», я не думаю, что смогу отменить его только с помощью unset($key). мне также понадобится путь к ключу.

3. У меня есть решение, чтобы отключить ключ, но оно не идеально. Требует eval()