Dostęp do tablicy asocjacyjnej przez indeks liczb całkowitych w PHP

93

Chcę ustawić wartość tablicy asocjacyjnej przy użyciu indeksu tablicy pary klucz / wartość. Na przykład:

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

Jak można to osiągnąć bez użycia ciągu kluczy?

Marty
źródło

Odpowiedzi:

189

Użyj array_keys .

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

Mam nadzieję że to pomoże.

Donovan
źródło
4
Na marginesie, dlaczego programiści PHP mieliby tworzyć tak nieintuicyjny sposób dostępu do tablicy?
Marty
3
@Marty ma to mniej wspólnego z tym, jak zaimplementowali go deweloperzy PHP, ale bardziej z twoim niezrozumieniem, jak działają tablice. Technicznie rzecz biorąc, powyżej nadal używa się nazwy asocjacyjnej. Nie ma korelacji między numerycznymi i asocjacyjnymi kluczami indeksu.
Gordon,
2
Tworzysz tablicę asocjacyjną, ponieważ to, czego szukasz, jest ważniejsze niż jej pozycja w tablicy. Myślę, że to dobra uwaga. Załóżmy, że masz tablicę z nazwiskami uczniów jako kluczami i adresami jako wartościami. Możesz dotrzeć do adresu ucznia po jego nazwie. Pozycja tablicy nie ma znaczenia. Możesz sortować tablicę według name of the student.
Donovan
@Gordon technicznie to prawda. Ale programista podaje liczbę, a nie łańcuch. Myślę, że to jest znaczenie without using a key string.
Donovan
2
@Albert, mapujesz ten numer na odpowiedni ciąg kluczy. To jednak nie oznacza, array[1] === $array['foo']że. Tablica może nadal zawierać inną wartość w $array[1]. Zauważ, że nie twierdzę, że twoje rozwiązanie jest złe. To założenie OP.
Gordon,
27

Nie ma korelacji między numerycznymi i asocjacyjnymi kluczami indeksu.

Kiedy mówisz, że chcesz ustawić wartość tablicy asocjacyjnej za pomocą indeksu tablicy klucza / wartości , musisz użyć danego klucza, ustawienie $array[1]nie jest tym samym, co ustawienie $array['foo'].

Rozważ tę tablicę

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

To da

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

Foo jest drugim elementem tablicy. To jest przesunięcie , ale nie ma to nic wspólnego z indeksem 1. Jak widać, w powyższej tablicy, indeks 1 jest powiązany baz. Błędem jest zakładanie, że tylko dlatego, że foojest pierwszym kluczem asocjacyjnym, ma on cokolwiek wspólnego z rzeczywistym kluczem numerycznym 1. Tak jak somenie koreluje z 2.

Podobnie w przypadku tablicy mieszanej, jak pokazano powyżej, rozwiązanie z array_keyssugerowanym w innym miejscu tej witryny nie będzie działać, ponieważ

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

da

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

Więc kiedy to robisz $array[$keys[1]], naprawdę robisz $array['foo']. Ale jeśli chcesz uzyskać dostęp do drugiej wartości asocjacyjnej w tej tablicy ( 'some'), nie możesz tego zrobić, $array[$keys[2]]ponieważ to dałoby wynik $array[1]i to jest baz.

Przesunięcie elementu jest całkowicie niezwiązane z jego kluczem lub wartością

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

naprawdę znaczy

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

co oznacza, że ​​element pod offsetem 0 to foo, chociaż jego klucz to 100. Jeśli chcesz wyodrębnić elementy z tablicy przez przesunięcie, musisz użyć

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

Utworzyłoby to tablicę zawierającą tylko element na trzeciej pozycji.

Lub możesz użyć ArrayIterator. W ArrayIteratorimplementuje Seekableinterfejs, który pozwala dążyć do położenia szczególnego / przesunięcie w tablicy, a następnie sprowadzić że:

$iterator = new ArrayIterator($array);
$iterator->seek(3);
echo $iterator->current(); // value
Gordon
źródło
Drobna nitka: "jeśli chcesz uzyskać dostęp do drugiej wartości asocjacyjnej w tej tablicy ('some'), nie możesz wykonać $ array [$ keys [2]], ponieważ dałoby to $ array [1] i to jest baz" Technicznie rzecz biorąc, to dlatego, że wszystkie klucze, w tym numeryczne, są kluczami asocjacyjnymi - 4 wartościami zwracanymi przez array_keys. Nie ma takiej encji jak „klucz niezespolony”. Jeśli chciałeś zwrócić uwagę, że nie możesz zwrócić drugiego klucza łańcucha (zakładając, że tablica kluczy zawiera tylko łańcuchy), to to, co mówisz, jest poprawne. $stringKeys = array_filter(array_keys($array), "is_string");daje klucze ciągów.
ToolmakerSteve
17

Chociaż array_keys()zezwala na dostęp do n-tego klucza, array_valuesdaje n-tą wartość.

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

wyświetli „Dwa”.

Czy istnieje przewaga jednego nad drugim? Cóż, jedyny pomniejszy, jaki widzę, to liczba dostępów do tablicy.

Ze array_keys()trzeba 3.

  1. Pobierz klucze z tablicy danych.
  2. Pobierz n-ty klucz z listy kluczy.
  3. Uzyskaj wartość przy użyciu n-tego klucza z tablicy danych.

Dzięki array_values(), potrzebujesz tylko 2.

  1. Pobierz wartości z tablicy danych.
  2. Uzyskaj n-tą wartość z listy wartości.

Ale z drugiej strony klucze są zwykle mniejsze, a dane mogą być bardzo zagnieżdżone, więc ogólnie rzecz biorąc, używanie klucza array_keys()jest prawdopodobnie bezpieczniejsze.

Richard A Quadling
źródło
3

Jeśli tablica jest duża, oba array_keysi array_valuesbędą marnotrawstwem, ponieważ przydzielą nową tablicę o tym samym rozmiarze co oryginalna, aby uzyskać n-ty klucz (lub wartość).

array_sliceakceptuje przesunięcie w postaci liczby całkowitej i działa na tablicach asocjacyjnych. Możesz go użyć, aby pobrać (i ustawić) n-ty klucz w stałym czasie.

// 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;
Jesse
źródło
2
Niezłe rozwiązanie!
Daan
1

Spróbuj tego. To działa dla Ciebie.

$result= array_values($my_arr); // Array with indexes you need
Murali krishna
źródło
1
Zachowaj ostrożność podczas publikowania w starym wątku, który ma już kilka odpowiedzi i zaakceptowaną odpowiedź. Musisz wyjaśnić, dlaczego Twoja nowa odpowiedź jest lepsza od dotychczasowych.
APC
0

Inną możliwością jest przekonwertowanie go na zwykłą tablicę:

$ arraybuff = implode ("~~~", $ my_arr);
$ my_arr = eksplodować ("~~~", $ arraybuff);

Gdzie „~~~” jest ogranicznikiem, który nie występuje w danych.

Teraz możesz uzyskać dostęp do tablicy za pomocą indeksów numerycznych równych przesunięciom.

Jeśli nadal chcesz zachować tablicę asocjacyjną, po prostu przypisz ją do innej zmiennej.

phreditor
źródło
Ponieważ zawsze i zawsze powinieneś wziąć pod uwagę, ten dokładny separator może wystąpić w twoich danych, ten pomysł działa tylko w 99,9999999%. Istnieje kilka rozwiązań, które będą działać w 100%, poza tym ustawia to procesor w dużo pracy i marnuje pamięć na prosty dostęp do tablicy.
user426486