comment autoriser les clés dupliquées dans le tableau php [dupliquer]

cette question a déjà une réponse ici:

est-ce que n'importe qui pourrait me faire savoir comment permettre à PHP array d'avoir des clés dupliquées. Lorsque j'essaie d'insérer une clé, valeur de paire avec une clé déjà existante, il remplace la valeur de clé précédente correspondante avec la nouvelle valeur. Y a-t-il un moyen de conserver les deux clés dupliquées ayant des valeurs différentes?

34
demandé sur sudh 2011-03-27 00:02:12

9 réponses

Vous pourriez avoir une seule clé qui a une valeur d'un tableau(ou un tableau multi-dimensionnel), qui contiendrait tous les éléments avec cette clé donnée. Un exemple pourrait être

$countries = array(
  "United States" => array("California", "Texas"),
  "Canada" => array("Ontario", "Quebec")
);
53
répondu Mike Lewis 2011-06-20 19:47:06
$array[$key][] = $value;

vous y accédez ensuite par:

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

etc.

notez que vous créez un tableau de tableaux en utilisant cette méthode.

27
répondu Matthew 2011-03-26 21:14:54

le point entier du tableau est d'avoir des Clés uniques. Si vous voulez stocker des paires de valeurs, alors:

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

Si vous avez beaucoup de dupes, alors cette alternative sera plus efficace:

<?php

if (array_key_exists($key, $array)) 
    $array[$key]['occurrences']++; 
else 
    $array[$key] = ['value'=>$value, 'occurrences'=>1];
13
répondu Kornel 2016-05-09 22:32:04

PHP ne permet pas cela. La meilleure solution est d'utiliser un tableau multidimensionnel. Par exemple...

<?php

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

?>

notez comment j'ai des doubles de clés nommées key1 .

maintenant si je veux appeler chaque instace de key1 , courir

<?php

    $desiredKeyName = "key1";

    foreach ($mArray as $aValue) {

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

            if ($key == $desiredKeyName) {

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

?>

et il reviendra

value1
value4
6
répondu Steve Robbins 2011-06-20 19:42:26

je vous présente: tableau D'Archives

exemple d'utilisation.

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

code de classe

<?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: parfois, vous avez besoin d'un piratage comme celui-ci pour obtenir le travail fait rapidement!

sa question peut avoir une forte controverse, et va à l'encontre des enseignements de l'informatique. mais il y a des cas où vous voulez que cela arrive. =X

par exemple, vous avez une base de code, qui manipule un ensemble spécifié d'objets array. Et en raison de son utilisation répétée (boucles? récursive?). Il remplace ou redéfinit le résultat. Jusqu'à la finale est donnée.

Et quand vous avez tout fait. Vous réalisez soudainement que vos spécifications client (ou vos) ont changé. Au lieu des données finales, vous voulez chaque donnée entre les deux (donc plus d'une donnée par clé). Et dans le malheureux cas, votre système était déjà terminé d'une manière si compliquée, il est une douleur dans le !@#$ pour tout changer pour fonctionner avec le tableau multidimensionnel facilement (ce qui signifie remplacer ne fonctionnerait pas, surtout si vous utilisez des appels dynamiques). Alors que faites-vous>??

c'était en fait un scénario que j'ai rencontré récemment, mais il y a un hack simple pour cela, qui assure toujours que tout votre code fonctionne encore, tout en conservant les anciennes données.

Le résultat final, un classe qui peut encore être traité comme n'importe quel autre objet. Mais a acquis une capacité d'archivage, de conserver de vieilles données. Il s'agit en quelque sorte d'un tableau multidimensionnel, avec l'index [0] accédé directement. Et cela fonctionne simplement en changeant la déclaration variable avec cet objet. Et toute modification apportée au paramètre objet, serait archivée. Pour un accès facile, avec peu ou pas de changement dans le programme de code entier=)

5
répondu PicoCreator 2016-02-10 10:14:28

j'ai trouvé une solution simple en travaillant sur un projet personnel.

comme je voulais une sorte de clés dupliquées, j'ai décidé de stocker les valeurs de mon tableau key=>dans un ordre inverse valeur=>clé où la valeur devient la clé et la clé devient la valeur, de cette façon je pourrais avoir des clés dupliquées qui sont en fait des valeurs. Je ne crée pas de valeurs dupliquées donc cela fonctionne dans ce cas précis.

si petit exemple:

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

si vous avez quelque chose comme:

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

alors j'irais avec une autre solution.

4
répondu darth lemon 2015-01-30 04:07:17

ce n'est pas tant que"tu ne peux pas le faire". Les inconvénients d'un tableau avec des clés dupliquées deviennent apparents quand vous avez réellement essayé de l'utiliser.

  • vous perdez la possibilité d'adresser le contenu individuellement. Pour les accès $array['duplicate'] vous ne verrez que la première entrée.
  • Donc, pratiquement, vous pouvez uniquement utiliser un tel objet dans un foreach qui voit chaque paire clé/valeur, indépendamment de l'ambiguïté.
  • voir ci-dessous, vous devez également décider comment gérer les tentatives de désactivation, ou si les entrées peuvent être écrasées du tout. Un mode append-only est le plus facile à implémenter. (Et c'est le cas de l'egde où cela pourrait avoir du sens.)

de toute façon, pour avoir aussi une réponse textuelle à la question: vous pouvez utiliser la syntaxe de tableau de PHPs mais avoir un objet d'accumulation à la place avec:

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;
    }
}
2
répondu mario 2011-06-20 15:54:38

comme dit porneL, le point entier des tableaux est que les clés sont uniques.

si vous voulez référencer plusieurs entrées dans un tableau, alors vous devez rechercher les valeurs du tableau.

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

cela va évidemment être plus efficace si vous maintenez des index. Le code ce n'est pas anodin.

si vous travaillez avec de grands ensembles de données, alors je recommande fortement d'utiliser un SGBD pour gérer les données. Si ce n'est pas pratique, puis utiliser une liste chaînée.

1
répondu symcbean 2011-06-16 11:29:45

ne Peut être atteint que par le biais d'un tableau multidimensionnel

0
répondu user431949 2011-06-14 20:08:33