как разрешить дублирование ключей в php-массиве

Может ли кто-нибудь дать мне знать, как разрешить php-массив иметь дубликаты ключей. Когда я пытаюсь вставить ключ, пара значений с уже существующим ключом, он перезаписывает значение соответствующего предыдущего ключа с новым значением. Есть ли способ, которым я мог бы поддерживать как дубликаты ключей, имеющих разные значения?

У вас может быть один ключ, который имеет значение массива (так называемый многомерный массив), который будет содержать все элементы с данным ключом. Примером может служить

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

Затем вы получаете доступ к нему через:

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

И т.п.

Обратите внимание, что вы создаете массив массивов, используя этот метод.

Вся точка массива состоит в том, чтобы иметь уникальные ключи. Если вы хотите сохранить пары значений, тогда:

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

Если у вас много обманов, то эта альтернатива будет более эффективной:

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

PHP этого не позволяет. Лучшим решением является использование многомерного массива. Например…

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

Обратите внимание, как у меня есть дубликаты ключей с именем key1 .

Теперь, если я хочу вызвать каждый ключ key1 , запустите

 <?php $desiredKeyName = "key1"; foreach ($mArray as $aValue) { foreach ($aValue as $key => $value) { if ($key == $desiredKeyName) { echo $value . "<br />"; } } } ?> 

и он вернется

 value1 value4 

Представляю вам: Архивный массив

Пример использования.

 <?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] ?> 

Код класса

 <?php /// /// An object array, which keeps an archived copy /// of all its previously set values. /// /// @author eugene@picoded.com /// 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: Иногда вам нужно взломать это, чтобы быстро выполнить работу!

Его вопрос может иметь сильные противоречия и противоречит учениям в области информатики. (прежде чем снимать, прочитайте все это). Но есть случаи, когда вы хотите, чтобы это произошло. = X

Например, у вас есть база кода, которая управляет указанным набором объектов массива. И из-за его повторного использования (петли ?, рекурсивные?). Он переопределяет или переопределяет результат. Пока не будет окончательный набор.

И когда у вас все будет сделано. Вы вдруг осознаете, что изменились ваши клиентские (или ваши) спецификации. Вместо конечных данных вы хотите, чтобы каждая отдельная информация находилась между ними (следовательно, требуется более 1 данных на ключ). И в неудачном случае ваша система уже была завершена таким сложным способом, это боль в @ @ $, чтобы изменить все, чтобы легко работать с многомерным массивом (что означает, что замена не будет работать, особенно если вы используете динамические вызовы). Так что ты делаешь> ??

Это был сценарий, с которым я сталкиваюсь в последнее время, но для этого есть простой взлом, который все еще гарантирует, что ваш код все еще работает, сохраняя при этом старые данные.

Конечный результат – класс, который все равно можно рассматривать как любой другой объект. Но у него есть возможность архивного хранения старых данных. Он сортирует многомерный массив с прямым доступом к [0]. И он работает просто путем изменения объявления переменной с этим объектом. И любые изменения, внесенные в параметр объекта, будут заархивированы. Для легкого доступа с минимальным или никаким изменением во всей программе кода =)

Я придумал простое решение, работая над личным проектом.

Поскольку мне нужны какие-то дублированные ключи, я решил сохранить значения массива key => в значении обратного порядка =>, где значение становится ключом, а ключ становится значением, таким образом, я мог бы иметь дубликаты ключей, которые на самом деле являются значения. Я не создаю дублированные значения, поэтому он работает в этом конкретном случае.

Итак, небольшой пример:

 $r = array ( 'banana'=>'FRUIT', 'apple'=>'FRUIT', 'broccoli'=>'VEG', 'peas'=>'VEG' ); function get_food_group ( $type, $bowl ) { return array_keys ( $bowl, $type ); } print_r ( get_food_group('FRUIT', $r) ); # PRINTS # # Array # ( # [0] => banana # [1] => apple # ) 

Если у вас будет что-то вроде:

 array ( 'banana' => 'FRUIT', 'peach' => 'FRUIT', 'banana' => 'YELLOW' ) 

Тогда я пошел бы с другим решением.

Как говорит porneL, вся суть массивов в том, что ключи уникальны.

Если вы хотите ссылаться на несколько записей в массиве, вам нужно искать значения массива.

  $arr=array( 0=>array('date'=>time(), 'ip'=>'127.0.0.1', url='index.php'), 1=>array('date'=>time(), 'ip'=>'192.168.1.2', url='index.php'), 2=>array('date'=>time(), 'ip'=>'127.0.0.1', url='other.php')); $matches=retrieve_keys_matching_subkey($arr, 'ip', '127.0.0.1'); foreach ($matches as $i) { print implode(' ', $arr[$i]) . "\n"; } function retrieve_keys_matching_subkey($arr, $subkey, $value) { $out=array(); foreach ($arr as $key=>$sub) { if ($sub[$subkey]===$value) { $out=$key; } } return $out; } 

Очевидно, что это будет более эффективно, если вы будете поддерживать индексы. Код для этого не является тривиальным.

Если вы работаете с большими наборами данных, я настоятельно рекомендую использовать СУБД для управления данными. Если это нецелесообразно, используйте связанный список.

Это не так, что «вы не можете этого сделать». Недостатки массива с дублирующимися ключами становятся очевидными, когда вы на самом деле пытались его использовать.

  • Вы теряете возможность индивидуально обращаться к контенту. Для доступа $array['duplicate'] вы увидите только первую запись.
  • Таким образом, вы практически можете использовать такой объект только в foreach который видит каждую пару ключ / значение независимо от двусмысленности.
  • См. Ниже, вы также должны решить, как обрабатывать отмененные попытки, или если записи могут быть перезаписаны вообще. Режим append-only проще всего реализовать. (И это пример egde, где это может иметь смысл.)

Во всяком случае, также есть стенографический ответ на вопрос: вы можете использовать синтаксис массива PHPs, но вместо этого есть объект накопления:

 class DuplicateArray implements ArrayAccess, Iterator, Countable { var $keys = array(), $values = array(); var $pointer = 0; // initialize from array function __construct($from=array()) { $this->keys = array_keys($from); $this->values = array_values($from); } // iteration function count() { return count($this->keys); } function current() { return $this->values[$this->position]; } function key() { return $this->keys[$this->position]; } function next() { $this->position++; } function rewind() { $this->position = 0; } function valid() { return isset($this->keys[$this->position]); } // just fetches the first found entry function offsetGet($key) { if (($i = array_search($key, $this->keys)) !== FALSE) { return $this->values[$i]; } else trigger_error("Undefined offset '$key'", E_USER_NOTICE); } // will only append new entries, not overwrite existing function offsetSet($key, $value) { $this->keys[] = $key; $this->values[] = $value; } // removes first matching entry function offsetUnset($key) { if (($i = array_search($key, $this->keys)) !== FALSE) { unset($this->keys[$i]); unset($this->values[$i]); // keep entries continuos for iterator $this->keys = array_values($this->keys); $this->values = array_values($this->values); } } function offsetExists($key) { return array_search($key, $this->keys) !== FALSE; } } не class DuplicateArray implements ArrayAccess, Iterator, Countable { var $keys = array(), $values = array(); var $pointer = 0; // initialize from array function __construct($from=array()) { $this->keys = array_keys($from); $this->values = array_values($from); } // iteration function count() { return count($this->keys); } function current() { return $this->values[$this->position]; } function key() { return $this->keys[$this->position]; } function next() { $this->position++; } function rewind() { $this->position = 0; } function valid() { return isset($this->keys[$this->position]); } // just fetches the first found entry function offsetGet($key) { if (($i = array_search($key, $this->keys)) !== FALSE) { return $this->values[$i]; } else trigger_error("Undefined offset '$key'", E_USER_NOTICE); } // will only append new entries, not overwrite existing function offsetSet($key, $value) { $this->keys[] = $key; $this->values[] = $value; } // removes first matching entry function offsetUnset($key) { if (($i = array_search($key, $this->keys)) !== FALSE) { unset($this->keys[$i]); unset($this->values[$i]); // keep entries continuos for iterator $this->keys = array_values($this->keys); $this->values = array_values($this->values); } } function offsetExists($key) { return array_search($key, $this->keys) !== FALSE; } } не class DuplicateArray implements ArrayAccess, Iterator, Countable { var $keys = array(), $values = array(); var $pointer = 0; // initialize from array function __construct($from=array()) { $this->keys = array_keys($from); $this->values = array_values($from); } // iteration function count() { return count($this->keys); } function current() { return $this->values[$this->position]; } function key() { return $this->keys[$this->position]; } function next() { $this->position++; } function rewind() { $this->position = 0; } function valid() { return isset($this->keys[$this->position]); } // just fetches the first found entry function offsetGet($key) { if (($i = array_search($key, $this->keys)) !== FALSE) { return $this->values[$i]; } else trigger_error("Undefined offset '$key'", E_USER_NOTICE); } // will only append new entries, not overwrite existing function offsetSet($key, $value) { $this->keys[] = $key; $this->values[] = $value; } // removes first matching entry function offsetUnset($key) { if (($i = array_search($key, $this->keys)) !== FALSE) { unset($this->keys[$i]); unset($this->values[$i]); // keep entries continuos for iterator $this->keys = array_values($this->keys); $this->values = array_values($this->values); } } function offsetExists($key) { return array_search($key, $this->keys) !== FALSE; } } 

Может быть достигнуто только через многомерный массив