Acessando uma matriz associativa por índice inteiro em PHP

92

Quero definir o valor de uma matriz associativa usando o índice da matriz do par chave / valor. Por exemplo:

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

Como isso pode ser feito sem usar a string de chave?

Marty
fonte

Respostas:

188

Use array_keys .

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

Espero que isto ajude.

Donovan
fonte
4
Como uma observação lateral, por que os desenvolvedores de PHP criariam uma maneira tão não intuitiva de acessar um array?
Marty
3
@Marty, isso tem menos a ver com como os desenvolvedores de PHP o implementaram, mas mais com seu mal-entendido sobre como os arrays funcionam. Tecnicamente, o acima ainda está usando o nome associativo. Não há correlação entre as chaves de índice numéricas e associativas.
Gordon
2
Você cria uma matriz associativa porque o que você está procurando é mais importante do que sua posição na matriz. Acho que é um bom ponto. Digamos que você tenha uma matriz com nomes de alunos como chaves e endereços como valores. Você pode acessar o endereço de um aluno pelo nome. A posição da matriz é irrelevante. E você pode classificar a matriz por name of the student.
Donovan
@Gordon, tecnicamente, é verdade. Mas o programador está fornecendo um número, não uma string. Acho que esse é o significado de without using a key string.
Donovan
2
@Albert, você está mapeando este número para a string de chave apropriada. Isso não significa isso array[1] === $array['foo']. A matriz ainda pode conter outro valor em $array[1]. Observe que não estou dizendo que sua solução esteja errada. É a suposição do OP.
Gordon
27

Não há correlação entre as chaves de índice numéricas e associativas.

Quando você diz que deseja definir o valor de um array associativo usando o índice do array da chave / valor , então você tem que usar a chave fornecida, configuração $array[1]não é o mesmo que configuração $array['foo'].

Considere esta matriz

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

Isso vai dar

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

O foo é o segundo elemento da matriz. Esse é o deslocamento , mas não tem nada a ver com o índice 1. Como você pode ver, no array acima, o índice 1 está associado baz. É errado presumir que apenas porque fooé a primeira chave associativa, isso tem algo a ver com a chave numérica real 1. Assim como somenão se correlaciona com 2.

Da mesma forma, para uma matriz mista como mostrado acima, a solução com array_keyssugerida em outro lugar neste site não funcionará, porque

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

darei

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

Então, quando você faz, $array[$keys[1]]está realmente fazendo $array['foo']. Mas se você quiser acessar o segundo valor associativo nesse array ( 'some'), você não pode fazer $array[$keys[2]]porque isso seria avaliado como $array[1]e pronto baz.

O deslocamento de um elemento não está totalmente relacionado à sua chave ou valor

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

realmente significa

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

o que significa que o elemento no deslocamento 0 é foo, embora sua chave seja 100. Se você deseja extrair elementos de uma matriz por deslocamento, você deve usar

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

Isso criaria uma matriz contendo apenas o elemento na terceira posição.

Ou você pode usar um ArrayIterator. O ArrayIteratorimplementa uma Seekableinterface que permite buscar uma posição / deslocamento específico na matriz e, em seguida, buscar:

$iterator = new ArrayIterator($array);
$iterator->seek(3);
echo $iterator->current(); // value
Gordon
fonte
Minor nit: "se você quiser acessar o segundo valor associativo nesse array ('some'), você não pode fazer $ array [$ keys [2]] porque isso seria avaliado como $ array [1] e isso é baz" Tecnicamente, isso porque todas as chaves, incluindo as numéricas, são chaves associativas - os 4 valores retornados por array_keys. Não existe uma entidade chamada "chave não associativa". Se você quisesse apontar que não pode retornar a segunda chave de string (assumindo que a matriz de chaves contém apenas strings), então o que você diz está correto. $stringKeys = array_filter(array_keys($array), "is_string");dá chaves de string.
ToolmakerSteve
17

Embora array_keys()permita o acesso à enésima chave, array_valuesfornecerá o enésimo valor.

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

irá imprimir 'Two'.

Existe uma vantagem de um sobre o outro? Bem, o único menor que posso ver é o número de acessos à matriz.

Com array_keys()você precisa de 3.

  1. Obtenha as chaves do array de dados.
  2. Obtenha a enésima chave da lista de chaves.
  3. Obtenha o valor usando a enésima chave da matriz de dados.

Com array_values(), você só precisa de 2.

  1. Obtenha os valores da matriz de dados.
  2. Obtenha o enésimo valor da lista de valores.

Mas, por outro lado, as chaves são normalmente menores e os dados podem ser muito aninhados, portanto, em geral, usar o array_keys()é provavelmente mais seguro.

Richard A Quadling
fonte
3

Se o array for grande, ambos array_keyse array_valuesserão um desperdício, pois eles alocarão um novo array do mesmo tamanho que o original, apenas para obter a enésima chave (ou valor).

array_sliceaceita um deslocamento de inteiro e funciona em matrizes associativas. Você pode usá-lo para obter (e definir) a enésima chave em tempo constante.

// 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
fonte
2
Boa solução aqui!
Daan
1

Experimente isso. Funciona para você.

$result= array_values($my_arr); // Array with indexes you need
Murali Krishna
fonte
1
Tenha cuidado ao postar em um tópico antigo que já possui várias respostas e uma resposta aceita. Você precisa explicar por que sua nova resposta é melhor do que as existentes.
APC
0

Outra possibilidade é convertê-lo em uma matriz normal:

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

Onde "~~~" é um delimitador que não ocorrerá em seus dados.

Agora você pode acessar o array usando índices numéricos iguais aos offsets.

Se você ainda precisa reter seu array associativo, apenas atribua-o a uma variável diferente.

phreditor
fonte
Como você deve sempre e sempre considerar, esse delimitador exato pode ocorrer em seus dados, essa ideia funciona apenas em 99,9999999%. Existem várias soluções que funcionarão 100%. Além disso, isso configura o processador para muito trabalho e memória desperdiçada para apenas um simples acesso ao array.
user426486