Подтвердить что ты не робот

Php: Array key case * нечувствительный * поиск?

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

Я хочу $myArray['somekeyname'] вернуть 7.
Есть ли способ сделать это, не манипулируя массивом?

Я не создаю массив, поэтому он не может управлять его клавишами

4b9b3361

Ответ 1

Вариант 1 - измените способ создания массива

Вы не можете сделать это без линейного поиска или изменения исходного массива. Наиболее эффективным подходом будет использование strtolower на клавишах, когда вы вставляете AND при поиске значений.

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

Ответ 2

Я знаю, что это старый вопрос, но самый изящный способ справиться с этой проблемой - использовать:

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

Ответ 3

Вы можете использовать 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;
    }
}

Ответ 4

Простым, но, может быть, дорогостоящим способом, является создание копии, затем используйте array_change_key_case($array_copy, CASE_LOWER), и после этого доступ array_copy['somekeyname']

Ответ 5

Я объединил идею Пола Диксона о создании сопоставления ключей и идеи Кендалла Хопкинса об использовании интерфейса ArrayAccess для сохранения знакомого способ доступа к массиву PHP.

Результат - это класс, который позволяет избежать копирования исходного массива и обеспечивает прозрачный доступ без учета регистра, при этом внутренне сохраняя дело с ключами. Ограничение: если ключи, не чувствительные к регистру (например, "Foo" и "foo" ), содержатся в начальном массиве или динамически добавляются, то последние записи будут перезаписывать предыдущие (что делает их недоступными).

По общему признанию, во многих случаях его (imo) гораздо более прямолинейный, чтобы просто вводить в нижний регистр ключи $lowercasedKeys = array_change_key_case($array, CASE_LOWER);, как это было предложено Mikpa.

Класс 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;
        }
    }
}

Ответ 7

Если вы назначаете их массиву, вы можете вводить строчные буквы, а также при строчном просмотре значения.

Без изменения массива, но всей структуры данных:

На самом деле громоздкий способ заключается в создании методов магии 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;
  } 
} 

Ответ 8

Мне также нужен способ возврата (первого) совпадения с учетом регистра. Вот что я придумал:

/**
 * 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];
}

Ответ 9

Вы можете вручную прокручивать массив и искать совпадение.

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

Ответ 10

В моем случае я хотел эффективный обходной путь, когда моя программа уже создавала массив с использованием цикла foreach из данных клиента, имеющих неизвестный случай, и я хотел сохранить случай клиента для последующего отображения в программе.

Мое решение состояло в том, чтобы создать отдельный массив $ CaseMap для сопоставления заданного ключа в нижнем регистре со смешанным ключом, используемым в массиве (здесь неактуальный код опущен):

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

Тогда поиск выглядит так:

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

а накладные расходы памяти - это просто массив $ CaseMap, который сопоставляет предположительно короткие ключи с короткими ключами.

Я не уверен, есть ли в PHP более эффективный способ генерирования $ CaseMap в случае, когда я еще не использовал foreach.

Ответ 11

Я знаю, что это старо, но в случае, если кому-то нужен быстрый простой способ сделать это, не изменяя исходный массив:

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