php:数组键大小写*不敏感*查找?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4240001/
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
php: Array keys case *insensitive* lookup?
提问by shealtiel
$myArray = array ('SOmeKeyNAme' => 7);
I want $myArray['somekeyname']
to return 7
.
Is there a way to do this, without manipulating the array?
我想$myArray['somekeyname']
回来7
。
有没有办法在不操作数组的情况下做到这一点?
I don't create the array, an thus can not control it's keys
我不创建数组,因此无法控制它的键
回答by Paul Dixon
Option 1 - change the way you create the array
选项 1 - 更改创建数组的方式
You can't do this without either a linear search or altering the original array. The most efficient approach will be to use strtoloweron keys when you insert AND when you lookup values.
如果不进行线性搜索或更改原始数组,您就无法做到这一点。最有效的方法是在查找值时插入 AND 时在键上使用strtolower。
$myArray[strtolower('SOmeKeyNAme')]=7;
if (isset($myArray[strtolower('SomekeyName')]))
{
}
If it's important to you to preserve the original case of the key, you could store it as a additional value for that key, e.g.
如果保留密钥的原始大小写对您很重要,您可以将其存储为该密钥的附加值,例如
$myArray[strtolower('SOmeKeyNAme')]=array('SOmeKeyNAme', 7);
Option 2 - create a secondary mapping
选项 2 - 创建辅助映射
As you updated the question to suggest this wouldn't be possible for you, how about you create an array providing a mapping between lowercased and case-sensitive versions?
当您更新问题以表明这对您来说是不可能的时,您如何创建一个数组来提供小写版本和区分大小写版本之间的映射?
$keys=array_keys($myArray);
$map=array();
foreach($keys as $key)
{
$map[strtolower($key)]=$key;
}
Now you can use this to obtain the case-sensitive key from a lowercased one
现在您可以使用它来从小写的密钥中获取区分大小写的密钥
$test='somekeyname';
if (isset($map[$test]))
{
$value=$myArray[$map[$test]];
}
This avoids the need to create a full copy of the array with a lower-cased key, which is really the only other way to go about this.
这避免了使用小写键创建数组的完整副本的需要,这实际上是解决此问题的唯一其他方法。
Option 3 - Create a copy of the array
选项 3 - 创建数组的副本
If making a full copy of the array isn't a concern, then you can use array_change_key_caseto create a copy with lower cased keys.
如果制作数组的完整副本不是问题,那么您可以使用array_change_key_case创建一个带有小写键的副本。
$myCopy=array_change_key_case($myArray, CASE_LOWER);
回答by Shawn
I know this is an older question but the most elegant way to handle this problem is to use:
我知道这是一个较老的问题,但处理这个问题的最优雅的方法是使用:
array_change_key_case($myArray); //second parameter is CASE_LOWER by default
In your example:
在你的例子中:
$myArray = array ('SOmeKeyNAme' => 7);
$myArray = array_change_key_case($myArray);
Afterwards $myArray will contain all lowercase keys:
之后 $myArray 将包含所有小写键:
echo $myArray['somekeyname'] will contain 7
Alternatively you can use:
或者,您可以使用:
array_change_key_case($myArray, CASE_UPPER);
Documentation be seen here: http://us3.php.net/manual/en/function.array-change-key-case.php
文档可以在这里看到:http: //us3.php.net/manual/en/function.array-change-key-case.php
回答by Kendall Hopkins
You could use ArrayAccess
interface to create a class that works with array syntax.
您可以使用ArrayAccess
interface 创建一个使用数组语法的类。
Example
例子
$lower_array_object = new CaseInsensitiveArray;
$lower_array_object["thisISaKEY"] = "value";
print $lower_array_object["THISisAkey"]; //prints "value"
or
或者
$lower_array_object = new CaseInsensitiveArray(
array( "SoMeThInG" => "anything", ... )
);
print $lower_array_object["something"]; //prints "anything"
Class
班级
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;
}
}
回答by Mikpa
A simple, but maybe expensive way, is to make a copy, then use array_change_key_case($array_copy, CASE_LOWER)
, and after that access array_copy['somekeyname']
一种简单但可能昂贵的方法是制作副本,然后使用array_change_key_case($array_copy, CASE_LOWER)
,然后访问array_copy['somekeyname']
回答by argonym
I combined Paul Dixon's idea of creating a mapping for the keys and Kendall Hopkins' idea of using the ArrayAccessinterface for retaining the familiar way of accessing a PHP array.
我结合了 Paul Dixon 为键创建映射的想法和 Kendall Hopkins 使用ArrayAccess接口保留访问 PHP 数组的熟悉方式的想法。
The result is a class that avoids copying the initial array and allows transparent case-insensitive access, while internally preserving the keys' case. Limitation: If case-insensitively equal keys (e.g. 'Foo' and 'foo') are contained in the initial array or are added dynamically, then latter entries will overwrite previous ones (rendering these inaccessible).
结果是一个避免复制初始数组并允许透明的不区分大小写访问的类,同时在内部保留键的大小写。限制:如果不区分大小写的相等键(例如“Foo”和“foo”)包含在初始数组中或动态添加,则后面的条目将覆盖先前的条目(使这些无法访问)。
Admittedly, in many cases its (imo) much more straight-forward to just lowercase the keys by $lowercasedKeys = array_change_key_case($array, CASE_LOWER);
, as suggested by Mikpa.
诚然,在许多情况下$lowercasedKeys = array_change_key_case($array, CASE_LOWER);
,正如 Mikpa 所建议的那样,它 (imo) 更直接地将键小写。
The CaseInsensitiveKeysArray class
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;
}
}
}
回答by Zaki Aziz
From the PHP site
来自 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
参考:http://us1.php.net/manual/en/function.array-key-exists.php#108226
回答by Bitwise Creative
I also needed a way to return (the first) case-insensitive key match. Here's what I came up with:
我还需要一种方法来返回(第一个)不区分大小写的键匹配。这是我想出的:
/**
* 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;
}
So, to answer the original question:
所以,要回答原来的问题:
$myArray = array('SOmeKeyNAme' => 7);
$test = 'somekeyname';
$key = get_array_ikey($test, $myArray);
if ($key !== false) {
echo $myArray[$key];
}
回答by icanhasserver
You can lowercase your keys when assigning them to the array and also lowercase them when looking up the value.
您可以在将键分配给数组时将它们小写,在查找值时也可以将它们小写。
Without modifying the array, but the whole data structure:
不修改数组,而是整个数据结构:
A really cumbersome way involves creating magic getter/setter methods, but would it really be worth the effort (note that the other methods have to be implemented too)?
一个非常麻烦的方法是创建魔法 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;
}
}
回答by JJJ
You could loop through the array manually and search for a match.
您可以手动遍历数组并搜索匹配项。
foreach( $myArray as $key => $value ) {
if( strtolower( $key ) == 'somekeyname' ) {
// match found, $value == $myArray[ 'SOmeKeyNAme' ]
}
}
回答by David Spector
In my case I wanted an efficient workaround where my program was already creating the array using a foreach loop from customer data having unknown case, and I wanted to preserve the customer's case for later display in the program.
在我的情况下,我想要一个有效的解决方法,我的程序已经使用 foreach 循环从具有未知案例的客户数据创建数组,并且我想保留客户的案例以供以后在程序中显示。
My solution was to create a separate array $CaseMap to map a given lowercase key to the mixedcase key used in the array (irrelevant code is omitted here):
我的解决方案是创建一个单独的数组 $CaseMap 将给定的小写键映射到数组中使用的混合键(此处省略了不相关的代码):
$CaseMap=[];
foreach ($UserArray as $Key=>$Value)
$CaseMap[strtolower($Key)]=$Key;
Then lookup is like this:
然后查找是这样的:
$Value=$UserArray[$CaseMap("key")];
and the memory overhead is just the $CaseMap array, which maps presumably short keys to short keys.
并且内存开销只是 $CaseMap 数组,它可能将短键映射到短键。
I'm not sure if PHP has a more efficient way to generate $CaseMap in the case where I'n not already using foreach.
在我还没有使用 foreach 的情况下,我不确定 PHP 是否有更有效的方法来生成 $CaseMap。