Может ли кто-нибудь дать мне знать, как разрешить php-массив иметь дубликаты ключей. Когда я пытаюсь вставить ключ, пара значений с уже существующим ключом, он перезаписывает значение соответствующего предыдущего ключа с новым значением. Есть ли способ, которым я мог бы поддерживать как повторяющиеся ключи, имеющие разные значения?
Как разрешать дубликаты ключей в php-массиве
Ответ 1
У вас может быть один ключ, который имеет значение массива (так называемый многомерный массив), который будет содержать все элементы с данным ключом. Примером может быть
$countries = array(
"United States" => array("California", "Texas"),
"Canada" => array("Ontario", "Quebec")
);
Ответ 2
$array[$key][] = $value;
Затем вы получаете доступ к нему через:
echo $array[$key][0];
echo $array[$key][1];
Etc.
Обратите внимание, что вы создаете массив массивов, используя этот метод.
Ответ 3
Вся суть массива состоит в том, чтобы иметь уникальные ключи. Если вы хотите сохранить пары значений, то:
$array[] = [$value1, $value2];
Если у вас много обманов, то эта альтернатива будет более эффективной:
<?php
if (array_key_exists($key, $array))
$array[$key]['occurrences']++;
else
$array[$key] = ['value'=>$value, 'occurrences'=>1];
Ответ 4
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
Ответ 5
Представляю вам: Архивный массив
Пример использования.
<?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 [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 ---!!!//
}
?>
TL;DR: Иногда вам нужно взломать это, чтобы быстро выполнить работу!
Его вопрос может иметь сильные противоречия и противоречит учению в области информатики. (прежде чем снимать, прочитайте все это). Но есть случаи, когда вы хотите, чтобы это произошло. = Х
Например, у вас есть база кода, которая управляет указанным набором объектов массива. И из-за его повторного использования (петли?, рекурсивные?). Он переопределяет или переопределяет результат. Пока не будет окончательный набор.
И когда у вас все будет сделано. Вы вдруг осознаете, что изменились ваши клиентские (или ваши) спецификации. Вместо конечных данных вы хотите, чтобы каждая отдельная информация находилась между ними (следовательно, требуется более 1 данных на ключ). И в неудачном случае ваша система уже была завершена таким сложным способом, это боль в @@$, чтобы изменить все, чтобы легко работать с многомерным массивом (что означает, что замена не будет работать, особенно если вы используете динамические вызовы). Итак, что вы делаете > ??
Это был сценарий, который я встречал недавно, но для этого есть простой взлом, который все еще гарантирует, что ваш код все еще работает, сохраняя при этом старые данные.
Конечный результат - класс, который по-прежнему можно рассматривать как любой другой объект. Но у него есть возможность архивного хранения старых данных. Он сортирует многомерный массив с прямым доступом к [0]. И он работает просто путем изменения объявления переменной с этим объектом. И любые изменения, внесенные в параметр объекта, будут заархивированы. Для легкого доступа с минимальным или никаким изменением во всей программе кода =)
Ответ 6
Я придумал простое решение, работая над личным проектом.
Поскольку мне нужны какие-то дублированные ключи, я решил сохранить значения массива = значение в значении обратного порядка = > , где значение становится ключом, а ключ становится значением, таким образом, я мог бы иметь дубликаты ключей, которые фактически являются значениями. Я не создаю дублированные значения, поэтому он работает в этом конкретном случае.
Итак, небольшой пример:
$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'
)
Тогда я пошел бы с другим решением.
Ответ 7
Как говорит 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;
}
Это, очевидно, будет более эффективным, если вы будете поддерживать индексы. Код для этого не является тривиальным.
Если вы работаете с большими наборами данных, я настоятельно рекомендую использовать СУБД для управления данными. Если это нецелесообразно, используйте связанный список.
Ответ 8
Это не так, что "вы не можете этого сделать". Недостатки массива с дублирующимися ключами становятся очевидными, когда вы на самом деле пытались его использовать.
- Вы теряете возможность индивидуально обращаться к контенту. Для доступа
$array['duplicate']
вы увидите только первую запись. - Таким образом, вы можете использовать такой объект только в
foreach
, который видит каждую пару ключ/значение независимо от двусмысленности. - См. ниже, вы также должны решить, как обрабатывать удаленные попытки, или если записи могут быть перезаписаны вообще. Режим append-only проще всего реализовать. (И это пример egde, где это может иметь смысл.)
Во всяком случае, также есть дословный ответ на вопрос: вы можете использовать синтаксис массива PHP, но вместо этого есть объект накопления:
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;
}
}
Ответ 9
Может быть достигнуто только через многомерный массив