Подтвердить что ты не робот

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

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

4b9b3361

Ответ 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

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