103

I want to set the value of an associative array using the array index of the key/value pair. For example:

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

How can this be accomplish this without using the key string?

6 Answers 6

209

Use array_keys.

$keys = array_keys($my_arr);
$my_arr[$keys[1]] = "not so much bling"; 
Sign up to request clarification or add additional context in comments.

5 Comments

As a side note, why would the PHP devs create such a non-intuitive way of accessing an array?
@Marty this has less to do with how PHP devs implemented it, but more with your misunderstanding of how arrays work. Technically, the above is still using the associative name. There is no correlation between numeric and associative index keys.
You create an associative array because what are you looking for is more important than its position in the array. I think this is a good point. Say you have an array with students names as keys and addresses as values. You can reach a student's address by its name. The position of the array it's irrelevant. And you can sort the array by name of the student.
@Gordon technically it's true. But the programmer is providing a number, not a string. I think this is the meaning of without using a key string.
@Albert you are mapping this number to the appropriate key string. That doesnt mean that array[1] === $array['foo'] though. The array could still contain another value at $array[1]. Note that I am not saying your solution is wrong. It's the OP's assumption.
30

There is no correlation between numeric and associative index keys.

When you say you want to set the value of an associative array using the array index of the key/value, then you have to use the given key, setting $array[1] is not the same as setting $array['foo'].

Consider this array

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

This will give

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

The foo is the second element in the array. That's the offset, but it has nothing to do with the index 1. As you can see, in that array above, index 1 is associated with baz. It is wrong to assume that just because foo is the first associative key it has anything to do with the actual numeric key 1. Just like some does not correlate to 2.

Likewise, for a mixed array like shown above, the solution with array_keys suggested elsewhere on this site will not work, because

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

will give

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

So when you do $array[$keys[1]] you are really doing $array['foo']. But if you wanted to access the second associative value in that array ('some'), you cannot do $array[$keys[2]] because that would evaluate to $array[1] and that's baz.

The Offset of an element is completely unrelated to it's key or value

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

really means

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

which means the element at offset 0 is foo although it's key is 100. If you want to extract elements from an array by offset, you have to use

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

This would create an array holding only the element at the third position.

Or you could use an ArrayIterator. The ArrayIterator implements a Seekable interface that lets you seek to a specific position/offset in the array and then fetch that:

$iterator = new ArrayIterator($array);
$iterator->seek(3);
echo $iterator->current(); // value

1 Comment

Minor nit: " if you wanted to access the second associative value in that array ('some'), you cannot do $array[$keys[2]] because that would evaluate to $array[1] and that's baz" Technically, that's because all keys, including numeric ones, are associative keys - the 4 values returned by array_keys. There is no such entity as a "non-associative key". If you meant to point out that you can't return the 2nd string key (by assuming the key array only contains strings), then what you say is correct. $stringKeys = array_filter(array_keys($array), "is_string"); gives string keys.
25

Whilst array_keys() allows access to the nth key, array_values will give you the nth value.

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

will output 'Two'.

Is there an advantage of one over the other? Well, the only minor one I can see is the number of array accesses.

With array_keys() you need to 3.

  1. Get the keys from the data array.
  2. Get the nth key from the list of keys.
  3. Get the value using the nth key from the data array.

With array_values(), you only need 2.

  1. Get the values from the data array.
  2. Get the nth value from the list of values.

But, on the other hand, keys are normally smaller and the data could be hugely nested, so, on balance, using the array_keys() is probably safer.

Comments

7

If the array is large, both array_keys and array_values will be wasteful since they will allocate a new array the same size as the original, just to get the nth key (or value).

array_slice accepts an integer offset and works on associative arrays. You can use it to get (and set) the nth key in constant time.

// 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;

1 Comment

Nice solution here!
1

Try this. It works for you.

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

2 Comments

Please be careful when posting to an old thread which already has several responses and an accepted answer. You need to explain why your new answer is better than the existing ones.
I know this is a super old comment, but it doesn't need to be "better". It simply needs to add something of value to what's already been provided.
0

Another possibility is to convert it to a normal array:

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

Where "~~~" is a delimiter that wont occur in your data.

Now you can access the array using numerical indexes equal to the offsets.

If you still need to retain your associative array, just assign it to a different variable.

1 Comment

Since you should always and ever consider, this exact delimiter can occur in your data, this idea just works in 99.9999999%. There are several solutions that will work 100%.Beside, this sets the processor to alot of work and wasted memory for just a simple array access.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.