79 votes

php : Recherche des clés de tableau sans tenir compte de la casse ?

$myArray = array ('SOmeKeyNAme' => 7);  

Je veux $myArray['somekeyname'] pour revenir 7 .
Existe-t-il un moyen de le faire, sans manipuler le tableau ?

Je ne crée pas le tableau, et donc je ne peux pas contrôler ses clés.

6 votes

Je pense qu'il est impossible de faire cela sans modifier ou copier le tableau. Vous pouvez copier le tableau et changer la casse des clés avec la fonction php array_change_key_case.

0 votes

C'est la réponse la plus appréciée, mais elle est écrite dans un commentaire... J'ai demandé si ce qui précède est possible, et la réponse est : non.

0 votes

Tout est possible. PHP est un logiciel libre, il suffit donc de modifier certains éléments internes et de recompiler ;)

98voto

Paul Dixon Points 122033

Option 1 - modifier la façon dont vous créez le tableau

Vous ne pouvez pas le faire sans effectuer une recherche linéaire ou modifier le tableau d'origine. L'approche la plus efficace sera d'utiliser strtolower sur les clés lorsque vous insérez ET lorsque vous consultez les valeurs.

 $myArray[strtolower('SOmeKeyNAme')]=7;

 if (isset($myArray[strtolower('SomekeyName')]))
 {

 }

S'il est important pour vous de préserver le cas original de la clé, vous pouvez le stocker comme une valeur supplémentaire pour cette clé, par exemple

$myArray[strtolower('SOmeKeyNAme')]=array('SOmeKeyNAme', 7);

Option 2 - créer une cartographie secondaire

Comme vous avez mis à jour la question pour suggérer que cela ne serait pas possible pour vous, que diriez-vous de créer un tableau fournissant une correspondance entre les versions minuscules et les versions sensibles à la casse ?

$keys=array_keys($myArray);
$map=array();
foreach($keys as $key)
{
     $map[strtolower($key)]=$key;
}

Maintenant vous pouvez utiliser ceci pour obtenir la clé sensible à la casse à partir d'une clé minuscule

$test='somekeyname';
if (isset($map[$test]))
{
     $value=$myArray[$map[$test]];
}

Cela évite de devoir créer une copie complète du tableau avec une clé en minuscules, ce qui est vraiment la seule autre façon de procéder.

Option 3 - Créer une copie du tableau

Si faire une copie complète du tableau n'est pas un problème, alors vous pouvez utiliser tableau_changement_de_key_case pour créer une copie avec des touches en minuscules.

$myCopy=array_change_key_case($myArray, CASE_LOWER);

4 votes

Je voulais savoir s'il existe un moyen direct de le faire. Je vois que ce n'est pas le cas. Votre réponse est une possibilité de contournement.

20 votes

Il existe également tableau_changement_de_key_case qui peuvent être utiles ici.

0 votes

@xpy : J'étais sur le point de suggérer la même chose, ça devrait être plus efficace aussi.

54voto

Shawn Points 1310

Je sais qu'il s'agit d'une question ancienne, mais la manière la plus élégante de traiter ce problème est d'utiliser :

array_change_key_case($myArray); //second parameter is CASE_LOWER by default

Dans votre exemple :

$myArray = array ('SOmeKeyNAme' => 7);
$myArray = array_change_key_case($myArray);

Ensuite, $myArray contiendra toutes les clés en minuscules :

echo $myArray['somekeyname'] will contain 7

Vous pouvez également utiliser :

array_change_key_case($myArray, CASE_UPPER);

La documentation peut être vue ici : http://us3.php.net/manual/en/function.array-change-key-case.php

20voto

Kendall Hopkins Points 12193

Vous pourriez utiliser ArrayAccess pour créer une classe qui fonctionne avec la syntaxe des tableaux.

Exemple

$lower_array_object = new CaseInsensitiveArray;
$lower_array_object["thisISaKEY"] = "value";
print $lower_array_object["THISisAkey"]; //prints "value"

ou

$lower_array_object = new CaseInsensitiveArray(
    array( "SoMeThInG" => "anything", ... )
);
print $lower_array_object["something"]; //prints "anything"

Classe

class CaseInsensitiveArray implements ArrayAccess
{
    private $_container = array();

    public function __construct( Array $initial_array = array() ) {
        $this->_container = array_map( "strtolower", $initial_array );
    }

    public function offsetSet($offset, $value) {
        if( is_string( $offset ) ) $offset = strtolower($offset);
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        if( is_string( $offset ) ) $offset = strtolower($offset);
        return isset($this->_container[$offset]);
    }

    public function offsetUnset($offset) {
        if( is_string( $offset ) ) $offset = strtolower($offset);
        unset($this->container[$offset]);
    }

    public function offsetGet($offset) {
        if( is_string( $offset ) ) $offset = strtolower($offset);
        return isset($this->container[$offset])
            ? $this->container[$offset]
            : null;
    }
}

14voto

Mikpa Points 1349

Un moyen simple, mais peut-être coûteux, est de faire une copie, puis d'utiliser array_change_key_case($array_copy, CASE_LOWER) et après cet accès array_copy['somekeyname']

0 votes

array_change_key_case ne modifie pas le tableau. Elle retourne une copie du tableau.

2voto

argonym Points 50

J'ai combiné l'idée de Paul Dixon de créer un mappage pour les touches et l'idée de Kendall Hopkins d'utiliser l'outil de gestion de l'identité de l'utilisateur. Accès aux tableaux pour conserver la manière familière d'accéder à un tableau PHP.

Le résultat est une classe qui évite de copier le tableau initial et permet un accès transparent insensible à la casse, tout en préservant en interne la casse des clés. Limitation : Si des clés insensibles à la casse (par exemple, 'Foo' et 'foo') sont contenues dans le tableau initial ou sont ajoutées dynamiquement, les dernières entrées écraseront les précédentes (ce qui les rendra inaccessibles).

Certes, dans de nombreux cas, il est (imo) beaucoup plus simple de simplement mettre les touches en minuscules par $lowercasedKeys = array_change_key_case($array, CASE_LOWER); comme le suggère Mikpa.

La classe CaseInsensitiveKeysArray

class CaseInsensitiveKeysArray implements ArrayAccess 
{
    private $container = array();
    private $keysMap   = array();

    public function __construct(Array $initial_array = array()) 
    {
        $this->container = $initial_array;

        $keys = array_keys($this->container);
        foreach ($keys as $key) 
        {
            $this->addMappedKey($key);
        }
    }

    public function offsetSet($offset, $value) 
    {
        if (is_null($offset)) 
        {
            $this->container[] = $value;
        }
        else 
        {
            $this->container[$offset] = $value;
            $this->addMappedKey($offset);
        }
    }

    public function offsetExists($offset) 
    {
        if (is_string($offset)) 
        {
            return isset($this->keysMap[strtolower($offset)]);
        }
        else 
        {
            return isset($this->container[$offset]);
        }
    }

    public function offsetUnset($offset) 
    {
        if ($this->offsetExists($offset)) 
        {
            unset($this->container[$this->getMappedKey($offset)]);
            if (is_string($offset)) 
            {
                unset($this->keysMap[strtolower($offset)]);
            }
        }
    }

    public function offsetGet($offset) 
    {
        return $this->offsetExists($offset) ? 
               $this->container[$this->getMappedKey($offset)] : 
               null;
    }

    public function getInternalArray() 
    {
        return $this->container;
    }

    private function addMappedKey($key) 
    {
        if (is_string($key)) 
        {
            $this->keysMap[strtolower($key)] = $key;
        }
    }

    private function getMappedKey($key) 
    {
        if (is_string($key)) 
        {
            return $this->keysMap[strtolower($key)];
        }
        else 
        {
            return $key;
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X