php 如何允许php数组中的重复键

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5445283/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 21:27:11  来源:igfitidea点击:

How to allow duplicate keys in php array

phparraysduplicates

提问by sudh

How to allow php array to have duplicate keys? When I try to insert a key, value pair with already existing key it overwrites the value of corresponding previous key with the new value. Is there a way that I could maintain both duplicate keys having different values?

如何允许php数组有重复的键?当我尝试插入一个键值对时,它会用新值覆盖相应先前键的值。有没有办法可以同时维护具有不同值的两个重复键?

回答by Mike Lewis

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")
);

回答by Matthew

$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.

请注意,您正在使用此方法创建数组数组。

回答by Kornel

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

回答by Steve Robbins

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

PHP 不允许这样做。最好的解决方案是使用多维数组。例如...

<?php

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

?>

Notice how I have duplicate keys named key1.

请注意我如何将重复的键命名为key1.

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

现在,如果我想调用 的每个实例key1,请运行

<?php

    $desiredKeyName = "key1";

    foreach ($mArray as $aValue) {

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

            if ($key == $desiredKeyName) {

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

?>

and it will return

它会回来

value1
value4

回答by PicoCreator

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!

TLDR:有时您需要像这样的 hack 才能快速完成工作!

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

他的问题可能会引起强烈的争议,并且与计算机科学的教义背道而驰。(在您拍摄之前,请阅读整篇文章)但是在某些情况下您希望这种情况发生。=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>??

当你做完所有的事情。您突然意识到您的客户(或您的)规格发生了变化。您需要中间的每个数据,而不是最终数据(因此每个键需要多于 1 个数据)。在不幸的情况下,您的系统已经以如此复杂的方式完成,在 !@#$ 中轻松更改所有内容以使用多维数组是一种痛苦(意味着替换不起作用,特别是如果您正在使用动态调用)。那你怎么办>??

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.

这实际上是我最近遇到的一个场景,但是对此有一个简单的 hack,它仍然可以确保您的所有代码仍然有效,同时仍然保留旧数据。

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 =)

最终结果是,仍然可以像对待任何其他对象一样对待一个类。但具有存档能力,可以保留旧数据。它排序一个多维数组,直接访问 [0] 索引。它的工作原理很简单,只需使用此对象更改变量声明即可。对对象参数所做的任何更改都将被存档。为了便于访问,整个代码程序中的更改最少或没有更改 =)

回答by darth lemon

I came up with a simple solution while working on a personal project.

我在处理个人项目时想出了一个简单的解决方案。

Since I wanted some sort of duplicated keys, I decided to store my array key=>values in a reverse order value=>key where value becomes the key and the key becomes the value, this way I could have duplicate keys which in fact are values. I am not creating duplicated values so it works in this specific case.

由于我想要某种重复的键,我决定以相反的顺序存储我的数组 key=>values value=>key,其中 value 成为 key,key 成为 value,这样我就可以拥有重复的键,实际上是值。我没有创建重复的值,因此它适用于这种特定情况。

So a little example:

所以一个小例子:

$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
# )

If you're gonna have something like:

如果你有这样的事情:

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

Then I would go with another solution.

然后我会选择另一种解决方案。

回答by mario

It's not so much that "you can't do it". The downsides to an array with duplicate keys becomes apparent when you actually tried to use it.

并不是说“你做不到”。当您实际尝试使用它时,具有重复键的数组的缺点变得很明显。

  • You lose the ability to address content individually. For $array['duplicate']accesses you will only ever see the first entry.
  • So practically you can only use such an object in a foreachwhich sees each key/value pair regardless of the ambiguity.
  • See below, you also have to decide how to handle unset attempts, or if entries can be overwritten at all. An append-only mode is easiest to implement. (And this is the egde case where it might make sense.)
  • 您将无法单独处理内容。对于$array['duplicate']访问,您只会看到第一个条目。
  • 所以实际上你只能在 a 中使用这样一个对象,foreach它可以看到每个键/值对,而不管是否有歧义。
  • 见下文,您还必须决定如何处理未设置的尝试,或者是否可以覆盖条目。仅附加模式最容易实现。(这是可能有意义的 egde 案例。)

Anyway, to also have a verbatim answer to the question: you can use PHPs array syntax but have an accumulation object instead with:

无论如何,也可以逐字回答这个问题:您可以使用 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;
    }
}

回答by symcbean

As porneL says, the whole point of arrays is that keys are unique.

正如porneL所说,数组的全部意义在于键是唯一的。

If you want to reference multiple entries in an array then you need to search the array values.

如果要引用数组中的多个条目,则需要搜索数组值。

  $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;
  }

This is obviously going to be more efficient if you maintain indexes. The code for this is not trivial.

如果您维护索引,这显然会更有效。用于此的代码并不简单。

If you're working with large datasets then I'd strongly recommend using a DBMS to manage the data. If that is not practical, then use a linked list.

如果您正在处理大型数据集,那么我强烈建议您使用 DBMS 来管理数据。如果这不切实际,则使用链表。

回答by user431949

Can only be achieved through a multidimensional array

只能通过多维数组来实现