Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicate keys in Array

Tags:

arrays

php

What is the best way to prevent duplicate key during type casting ?

Example :

//Credits @bwoebi
$obj = (object)array(1,2,3);
$obj->{1} = "Duplicate key 1";
$obj->{2} = "Duplicate key 2";
$obj->{3} = "Duplicate key 3";
$array = (array)$obj ;
print_r($array);

Output

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [1] => Duplicate key 1
    [2] => Duplicate key 2
    [3] => Duplicate key 3
)

Now i know some smart people would say its because one key is string and the other int use var_dump

var_dump($array);

Output

array (size=6)
  0 => int 1
  1 => int 2
  2 => int 3
  '1' => string 'Duplicate key 1' (length=15)
  '2' => string 'Duplicate key 2' (length=15)
  '3' => string 'Duplicate key 3' (length=15)

But the main issue is there is no way to even get the key

echo $array['1'] ,PHP_EOL;     //Expected Duplicate key 1
echo $array[1] ,PHP_EOL;

Output

2
2

Is there any workaround to this issue without having to loop ? Obviously i would never make this mistake unless @PeeHaa埽 gives be beer again, but I think any answer should help educated PHP developers.

Note. - This can easly be resolved with array_values , sort or any php function that changes key position

Example

sort($array);
print_r($array);

Output

Array
(
    [0] => Duplicate key 1
    [1] => Duplicate key 2
    [2] => Duplicate key 3
    [3] => 1
    [4] => 2
    [5] => 3
)
like image 707
Baba Avatar asked Oct 21 '22 12:10

Baba


2 Answers

You can use array_values function to reset array keys.

Try this:

$obj = (object)array(1,2,3);
$obj->{1} = "Duplicate key 1";
$obj->{2} = "Duplicate key 2";
$obj->{3} = "Duplicate key 3";
$array = (array)$obj ;

$array = array_values($array);
print_r($array);

Produces this:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => Duplicate key 1
    [4] => Duplicate key 2
    [5] => Duplicate key 3
)

Or you can even use array_values before casting like this:

$array = array_values((array)$obj);

Hope this helps!

like image 98
Matija Avatar answered Oct 27 '22 10:10

Matija


Maybe not the best solution, but using a custom function to cast arrays to objects would solve part of the problem.

// function that convers an array to an object, and prefixes the numeric values with a string
function toObj(Array $arr, $prefix = '_', $convertAll = false ) {
    foreach ($arr as $key => $value) {
        if (is_numeric($key) || $convertAll) {
            unset($arr[$key]);
            $arr[$prefix . $key] = $value;
        }
    }
    return (object)$arr;
}

$obj = toObj(array(1, 2, 3));
$obj->{'_0'} = "Duplicate key 0"; // either this way
$obj->_1 = "Duplicate key 1"; // or this way
$obj->{'_2'} = "Duplicate key 2";
$array = (array)$obj;
print_r($array);

The result is:

Array
(
    [_0] => Duplicate key 0
    [_1] => Duplicate key 1
    [_2] => Duplicate key 2
)

Although this is similar to the array_values solution, it has the benefit of still keeping the keys, at least to a certain degree.

like image 35
Vlad Preda Avatar answered Oct 27 '22 09:10

Vlad Preda