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


92

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

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

Як це можна досягти, не використовуючи рядок ключів?

Відповіді:


188

Використовуйте ключі масиву .

$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]. Зауважте, що я не кажу, що ваше рішення неправильне. Це припущення OP.
Гордон,

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], і це базово" Технічно, це тому, що всі ключі, включаючи числові, є асоціативними ключами - 4 значення, що повертаються array_keys. Не існує такої сутності, як "неасоціативний ключ". Якщо ви мали намір зазначити, що ви не можете повернути ключ 2-го рядка (припускаючи, що масив ключів містить лише рядки), тоді те, що ви говорите, є правильним. $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
Приємне рішення тут!
Даан

1

Спробуйте це. Це працює для вас.

$result= array_values($my_arr); // Array with indexes you need

1
Будьте обережні, надсилаючи повідомлення до старої теми, яка вже має кілька відповідей та прийняту відповідь. Вам потрібно пояснити, чому ваша нова відповідь краща за існуючу.
APC

0

Інша можливість - перетворити його на звичайний масив:

$ arraybuff = implode ("~~~", $ my_arr);
$ my_arr = вибухнути ("~~~", $ arraybuff);

Де "~~~" - це роздільник, який зазвичай не зустрічається у ваших даних.

Тепер ви можете отримати доступ до масиву за допомогою числових індексів, рівних зміщенням.

Якщо вам все-таки потрібно зберегти асоціативний масив, просто призначте його іншій змінній.


Оскільки вам слід завжди і завжди враховувати, що саме цей роздільник може міститися у ваших даних, ця ідея просто працює на 99,9999999%. Є кілька рішень, які будуть працювати на 100%. Крім того, це налаштовує процесор на велику кількість роботи і марну пам’ять для простого доступу до масиву.
user426486
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.