php:数组键案例*不敏感*查找?

时间:2010-11-21 19:56:26

标签: php arrays

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

我希望$myArray['somekeyname']返回7 有没有办法做到这一点,而无需操纵数组?

我没有创建数组,因此无法控制它的键

12 个答案:

答案 0 :(得分:72)

选项1 - 更改创建阵列的方式

如果没有线性搜索或更改原始数组,则无法执行此操作。当您查找值时,最有效的方法是在键上使用strtolower

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

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

 }

如果您保留密钥的原始情况很重要,则可以将其存储为该密钥的附加值,例如

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

选项2 - 创建辅助映射

当您更新问题以表明这对您来说不可能时,如何创建一个提供小写和区分大小写版本之间映射的数组?

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

现在,您可以使用它来从小写的

中获取区分大小写的密钥
$test='somekeyname';
if (isset($map[$test]))
{
     $value=$myArray[$map[$test]];
}

这样就无需使用较低的密钥创建数组的完整副本,这实际上是另一种方法。

选项3 - 创建数组的副本

如果不考虑制作阵列的完整副本,那么您可以使用array_change_key_case创建一个带有较低外壳密钥的副本。

$myCopy=array_change_key_case($myArray, CASE_LOWER);

答案 1 :(得分:41)

我知道这是一个较旧的问题,但处理此问题的最佳方法是使用:

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

在你的例子中:

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

之后$ myArray将包含所有小写的键:

echo $myArray['somekeyname'] will contain 7

或者您也可以使用:

array_change_key_case($myArray, CASE_UPPER);

此处可以看到文档:http://us3.php.net/manual/en/function.array-change-key-case.php

答案 2 :(得分:14)

您可以使用ArrayAccess接口创建一个使用数组语法的类。

示例

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

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

<强>类

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

答案 3 :(得分:14)

一种简单但可能很昂贵的方法是制作副本,然后使用array_change_key_case($array_copy, CASE_LOWER),之后访问array_copy['somekeyname']

答案 4 :(得分:2)

我结合了Paul Dixon为密钥创建映射的想法和Kendall Hopkins使用ArrayAccess接口保留熟悉的访问PHP数组的方法的想法。

结果是一个类,它避免复制初始数组并允许透明的不区分大小写的访问,同时在内部保留键的大小写。限制:如果不区分大小写的键(例如'Foo'和'foo')包含在初始数组中或者是动态添加的,那么后面的条目将覆盖以前的条目(使这些条目无法访问)。

不可否认,在很多情况下,按照Mikpa的建议,它(imo)更加直截了当地按$lowercasedKeys = array_change_key_case($array, CASE_LOWER);小写。

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

答案 5 :(得分:2)

来自PHP网站

function array_ikey_exists($key, $haystack){
    return array_key_exists(strtolower($key), array_change_key_case($haystack));    
}

Referance:http://us1.php.net/manual/en/function.array-key-exists.php#108226

答案 6 :(得分:1)

您可以在将键分配给数组时将其小写,并在查找值时将其小写。

不修改数组,但整个数据结构:

一个非常麻烦的方法是创建魔术getter / setter方法,但是真的值得付出努力(请注意其他方法也必须实现)?

<?php 

class CaseInsensitiveArray
{ 

  protected $m_values;

  public function __construct()
  {
    $this->m_values = array();
  } 

  public function __get($key)
  { 
    return array_key_exists($key, $this->m_values) ? $this->m_values[$key] : null;
  } 

  public function __set($key, $value)
  { 
    $this->m_attributes[$key] = $value;
  } 
} 

答案 7 :(得分:1)

我还需要一种方法来返回(第一个)不区分大小写的键匹配。这就是我想出的:

/**
 * Case-insensitive search for present array key
 * @param string $needle
 * @param array $haystack
 * @return string|bool The present key, or false
 */
function get_array_ikey($needle, $haystack) {
    foreach ($haystack as $key => $meh) {
        if (strtolower($needle) == strtolower($key)) {
            return (string) $key;
        }
    }
    return false;
}

所以,回答原来的问题:

$myArray = array('SOmeKeyNAme' => 7);
$test = 'somekeyname';
$key = get_array_ikey($test, $myArray);
if ($key !== false) {
    echo $myArray[$key];
}

答案 8 :(得分:0)

您可以手动遍历数组并搜索匹配项。

foreach( $myArray as $key => $value ) {
    if( strtolower( $key ) == 'somekeyname' ) {
        // match found, $value == $myArray[ 'SOmeKeyNAme' ]
    }
}

答案 9 :(得分:0)

对于我来说,我想要一种有效的解决方法,其中程序已经使用foreach循环从具有未知大小写的客户数据中使用foreach循环创建了数组,并且我希望保留客户的案例以供以后在程序中显示。

我的解决方案是创建一个单独的数组$ CaseMap,以将给定的小写键映射到该数组中使用的混合大小写键(此处省略了无关的代码):

$CaseMap=[];
foreach ($UserArray as $Key=>$Value)
    $CaseMap[strtolower($Key)]=$Key;

然后查找是这样的:

$Value=$UserArray[$CaseMap("key")];

并且内存开销只是$ CaseMap数组,该数组大概将短键映射到短键。

在不确定我尚未使用foreach的情况下,我不确定PHP是否有更有效的方法来生成$ CaseMap。

答案 10 :(得分:0)

我只是遇到了同样的问题,所以无法更改原始数组。我为此使用了一些数组函数。

参数

$search = "AbCd";
$array = array("AbcD"=>"11","Bb"=>"22");

解决方案

$lower_search = strtolower($search);
$array_of_keys = array_map("strtolower",array_keys($array));
$idx = array_search($lower_search,$array_of_keys);
if($idx !== FALSE)
    echo array_values($array)[$idx];

缩短时间

if(($idx=array_search(strtolower($search),array_map("strtolower",array_keys($array))))!==FALSE)
    echo array_values($array)[$idx];

答案 11 :(得分:-1)

我知道这是旧的,但万一其他人需要一个快速简单的方法来做到这一点而不实际更改原始数组:

function array_key_i($needle, $haystack){
  $key=array_search(strtolower($search), array_combine(array_keys($array),array_map('strtolower', array_keys($array))));
  return ($key!==false);
}

$array=array('TeSt1'=>'maybe');
$search='test1';

array_key_i($search, $array); // returns true