Доступ к ассоциативному массиву по целочисленному индексу в PHP

93

Я хочу установить значение ассоциативного массива, используя индекс массива пары ключ / значение. Например:

$my_arr = array( "bling" => "some bling", "bling2" => "lots O bling" );
$my_arr[1] = "not so much bling";  // Would change the value with key bling2.

Как это можно сделать без использования ключевой строки?

Марти
источник

Ответы:

189

Используйте array_keys .

$keys = array_keys($my_arr);
$my_arr[$keys[1]] = "not so much bling";

Надеюсь это поможет.

Донован
источник
4
В качестве примечания, почему разработчики PHP создали такой неинтуитивный способ доступа к массиву?
Марти
3
@Marty, это не столько связано с тем, как разработчики PHP его реализовали, сколько с вашим непониманием того, как работают массивы. Технически вышеупомянутое все еще использует ассоциативное имя. Между числовыми и ассоциативными индексными ключами нет корреляции.
Гордон
2
Вы создаете ассоциативный массив, потому что то, что вы ищете, более важно, чем его позиция в массиве. Я думаю, это хороший момент. Допустим, у вас есть массив с именами студентов в качестве ключей и адресами в качестве значений. Вы можете связаться с адресом студента по его имени. Положение массива не имеет значения. И вы можете отсортировать массив по name of the student.
Донован
@Gordon технически это правда. Но программист предоставляет число, а не строку. Думаю, в этом смысл without using a key string.
Донован
2
@Albert, вы сопоставляете это число с соответствующей строкой ключей. Но это не значит array[1] === $array['foo']. В массиве все еще может содержаться другое значение в $array[1]. Обратите внимание, что я не говорю, что ваше решение неверно. Это предположение ОП.
Гордон
27

Между числовыми и ассоциативными индексными ключами нет корреляции.

Когда вы говорите, что хотите установить значение ассоциативного массива, используя индекс массива ключа / значения , тогда вы должны использовать данный ключ, настройка $array[1]не совпадает с настройкой $array['foo'].

Рассмотрим этот массив

print_r( array('foo', 'foo' => 'bar', 'baz', 'some' => 'value') );

Это даст

Array
(
    [0] => foo
    [foo] => bar
    [1] => baz
    [some] => value
)

Foo - второй элемент в массиве. Это смещение , но оно не имеет ничего общего с индексом 1. Как вы можете видеть, в приведенном выше массиве индекс 1 связан с baz. Неверно предполагать, что именно потому, что fooэто первый ассоциативный ключ, он имеет какое-либо отношение к фактическому числовому ключу 1. Точно так же, как someне коррелирует с 2.

Аналогичным образом, для смешанного массива, подобного показанному выше, решение, array_keysпредложенное в другом месте на этом сайте, не будет работать, потому что

print_r( array_keys(array('foo', 'foo' => 'bar', 'baz', 'some' => 'value')) );

дам

Array
(
    [0] => 0
    [1] => foo
    [2] => 1
    [3] => some
)

Итак, когда вы это делаете, $array[$keys[1]]вы действительно делаете $array['foo']. Но если вы хотите получить доступ ко второму ассоциативному значению в этом массиве ( 'some'), вы не можете этого сделать, $array[$keys[2]]потому что это будет оценивать $array[1]и это baz.

Смещение элемента совершенно не связано с его ключом или значением.

print_r(
    array(
        100    => 'foo',
        'foo'  => 'bar',
        50     => 'baz',
        'some' => 'value'
    )
);

действительно означает

Array
( //key       value     offset/position
    [100]  => foo       // 0
    [foo]  => bar       // 1
    [50]   => baz       // 2
    [some] => value     // 3
)

что означает, что элемент со смещением 0 равен foo, хотя его ключ равен 100. Если вы хотите извлечь элементы из массива по смещению, вы должны использовать

$third = array_splice($array, 2, 1);
echo $third[0]; // baz

Это создаст массив, содержащий только элемент в третьей позиции.

Или вы можете использовать расширение ArrayIterator. В ArrayIteratorреализует Seekableинтерфейс , который позволяет искать в определенной позиции / смещение в массиве , а затем принести что:

$iterator = new ArrayIterator($array);
$iterator->seek(3);
echo $iterator->current(); // value
Гордон
источник
Незначительная нить: «если вы хотите получить доступ ко второму ассоциативному значению в этом массиве ('some'), вы не можете сделать $ array [$ keys [2]], потому что это будет оценивать как $ array [1] и это baz» Технически, это потому, что все ключи, включая числовые, являются ассоциативными ключами - 4 значения, возвращаемые функцией array_keys. Не существует такой сущности, как «неассоциативный ключ». Если вы хотели указать, что вы не можете вернуть ключ второй строки (предполагая, что массив ключей содержит только строки), то то, что вы говорите, правильно. $stringKeys = array_filter(array_keys($array), "is_string");дает строковые ключи.
ToolmakerSteve
17

Пока array_keys()разрешен доступ к n-му ключу, array_valuesвы получите n-е значение.

<?php
$array = [
   0     => 'Zero',
   '1'   => 'One',
   'Two' => 'Two',
];
echo array_values($array)[2];
?>

выведет «Два».

Есть ли у одного преимущество перед другим? Ну, единственное, что я вижу, это количество обращений к массиву.

С array_keys()вас нужно 3.

  1. Получите ключи из массива данных.
  2. Получите n-й ключ из списка ключей.
  3. Получите значение с помощью n-го ключа из массива данных.

С array_values(), вам нужно всего 2.

  1. Получите значения из массива данных.
  2. Получите n-е значение из списка значений.

Но, с другой стороны, ключи обычно меньше по размеру, а данные могут быть сильно вложенными, поэтому в целом использование ключа, array_keys()вероятно, безопаснее.

Ричард Квадлинг
источник
3

Если массив большой, оба array_keysи array_valuesбудут расточительными, поскольку они выделят новый массив того же размера, что и исходный, просто чтобы получить n-й ключ (или значение).

array_sliceпринимает целочисленное смещение и работает с ассоциативными массивами. Вы можете использовать его для получения (и установки) n-го ключа за постоянное время.

// This will at most allocate 2 temporary arrays of 1 element each
$key = array_keys(array_slice($array, $n, 1, true))[0];

$array[$key] = $value;
Джесси
источник
2
Хорошее решение!
Daan
1

Попробуй это. Это работает на вас.

$result= array_values($my_arr); // Array with indexes you need
Мурали Кришна
источник
1
Будьте осторожны при отправке сообщений в старую тему, в которой уже есть несколько ответов и принятый ответ. Вам нужно объяснить, почему ваш новый ответ лучше существующих.
APC
0

Другая возможность - преобразовать его в обычный массив:

$ arraybuff = implode ("~~~", $ my_arr);
$ my_arr = explode ("~~~", $ arraybuff);

Где «~~~» - это разделитель, который не встречается в ваших данных.

Теперь вы можете получить доступ к массиву, используя числовые индексы, равные смещениям.

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

фредитор
источник
Поскольку вы всегда должны учитывать, что этот точный разделитель может встречаться в ваших данных, эта идея работает только в 99.9999999%. Есть несколько решений, которые будут работать на 100%. Кроме того, это заставляет процессор много работать и тратить впустую память только для простого доступа к массиву.
user426486