How to allow duplicate keys in php array [duplicate]

You could have a single key that has a value of an array(aka a multi-dimensional array), which would contain all the elements with that given key. An example might be

$countries = array(
  "United States" => array("California", "Texas"),
  "Canada" => array("Ontario", "Quebec")
);

$array[$key][] = $value;

You then access it via:

echo $array[$key][0];
echo $array[$key][1];

Etc.

Note you are creating an array of arrays using this method.


The whole point of array is to have unique keys. If you want to store pairs of values, then:

$array[] = [$value1, $value2];

If you have many dupes, then this alternative will be more efficient:

<?php

if (array_key_exists($key, $array)) 
    $array[$key]['occurrences']++; 
else 
    $array[$key] = ['value'=>$value, 'occurrences'=>1];

PHP doesn't allow for this. The best solution is to use a multidimensional array. For instance...

<?php

    $mArray = array(array("key1" => "value1"),
                    array("key2" => "value2"),
                    array("key3" => "value3"),
                    array("key1" => "value4"));

?>

Notice how I have duplicate keys named key1 .

Now if I want to call each instace of key1, run

<?php

    $desiredKeyName = "key1";

    foreach ($mArray as $aValue) {

        foreach ($aValue as $key => $value) {

            if ($key == $desiredKeyName) {

                echo $value . "<br />";
            }
        }
    }

?>

and it will return

value1
value4

I present you : Archive Array

Sample usage.

<?php
$arch = new archiveArray(); //Class setup

// Set and overwrite the data few times
$arch -> data = 'one';
$arch -> data = 2;
$arch -> data = 'tree XD';

// Get the latest data, as per expected behaviour of an array object
var_dump( $arch -> data ); // 'tree XD'

// Get its previously set archived values
var_dump( $arch -> getArchived( 'data' ) ); // ['one', 2]
?>

Class code

<?php
///
/// An object array, which keeps an archived copy 
/// of all its previously set values. 
///
/// @author [email protected]
///
class archiveArray {

    public $arch_data = array();
    public $arch_archive = array();

    public function archiveArray() {
        $arch_data = array();
        $arch_archive = array();
    }

    public function setData($name, $value) {
        if( array_key_exists( $name, $this -> arch_data ) ) {

            if( !array_key_exists( $name, $this -> arch_archive ) ) {
                $this -> arch_archive[ $name ] = array();
            } else {
                if( !is_array($this -> arch_archive[ $name ] ) ) {
                    $this -> arch_archive[ $name ] = array();
                }
            }

            array_push( $this -> arch_archive[ $name ] , $this -> arch_data[ $name ] );

        }

        $this -> arch_data[ $name ] = $value;
    }

    public function getData($name) {
        return $this -> arch_data[ $name ];
    }

    public function getArchived($name) {
        if( array_key_exists( $name, $this -> arch_archive ) ) {
            return $this -> arch_archive[ $name ];
        }
        return null;
    }

    //!!!--- OVERLOAD functionalities START ---!!!//
    public function __set($name, $value) {      //Uses the 'set' to create a node in the default type setting
        $this -> setData($name, $value);
    }

    public function __get($name) {
        return $this -> getData($name);
    }
    //!!!--- OVERLOAD functionalities END ---!!!//
}
?>

TLDR: Sometimes you need a hack like this to get the job done fast!

His question may have strong controversy, and goes against the teachings of computer science. (before you shoot, read the whole thing) But there are cases where you want this to happen. =X

For example, you have a code base, which manipulates a specified set of array objects. And due to its repeated usage (loops?, recursive?). It overrides or redefines the result. Till the final set is given.

And when you have everything all done. You suddenly realise your client (or your) specifications changed. Instead of the final data, you want every single data in between (hence wanting more then 1 data per key). And in the unfortunate case, your system was already completed in such a complicated way, it is a pain in the !@#$ to change everything to work with multi-dimensional array easily (meaning replace would not work, especially if you are using dynamic calls). So what do you do>??

This was actually a scenario i encounter recently, but there is a simple hack for this, that still ensures all your code still work, while still keeping the old data.

The end result, a class that can still be treated like any other object. But has gain an archive ability, to keep old data. It sorta a multi-dimensional array, with the [0] index accessed directly. And it works simply by changing the variable declaration with this object. And any changes made to the object parameter, would be archived. For easy access, with minimal or no change in the entire code program =)