development

PHP : 배열 키 대소 문자를 구분하지 않음 * 조회?

big-blog 2020. 12. 3. 08:06
반응형

PHP : 배열 키 대소 문자를 구분하지 않음 * 조회?


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

나는 $myArray['somekeyname']돌아가고 싶다 7.
배열을 조작하지 않고이를 수행 할 수있는 방법이 있습니까?

배열을 만들지 않으므로 키를 제어 할 수 없습니다.


옵션 1-어레이 생성 방식 변경

선형 검색을하지 않거나 원래 배열을 변경하지 않고는이를 수행 할 수 없습니다. 가장 효율적인 방법은 값을 조회 할 때 AND를 삽입 할 때 키에 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);

나는 이것이 오래된 질문이라는 것을 알고 있지만이 문제를 처리하는 가장 우아한 방법은 다음을 사용하는 것입니다.

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


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

간단하지만 비용이 많이 드는 방법은 복사본을 만든 다음을 사용 array_change_key_case($array_copy, CASE_LOWER)하고 해당 액세스 후에array_copy['somekeyname']


저는 키 매핑을 만드는 Paul Dixon의 아이디어와 PHP 배열에 접근하는 익숙한 방법을 유지하기 위해 ArrayAccess 인터페이스를 사용하는 Kendall Hopkins의 아이디어를 결합했습니다 .

결과는 초기 배열 복사를 피하고 대소 문자를 구분하지 않는 투명한 액세스를 허용하는 동시에 키의 대소 문자를 내부적으로 보존하는 클래스입니다. 제한 : 대소 문자를 구분하지 않는 동일한 키 (예 : 'Foo'및 'foo')가 초기 배열에 포함되어 있거나 동적으로 추가되면 후자의 항목이 이전 항목을 덮어 씁니다 (액세스 불가능하게 렌더링 됨).

물론 많은 경우 $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;
        }
    }
}

PHP 사이트에서

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

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


또한 (첫 번째) 대소 문자를 구분하지 않는 키 일치를 반환하는 방법이 필요했습니다. 내가 생각 해낸 것은 다음과 같습니다.

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

키를 배열에 할당 할 때 소문자로 지정하고 값을 찾을 때 소문자로 지정할 수도 있습니다.

배열을 수정하지 않고 전체 데이터 구조 :

정말 성가신 방법은 매직 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;
  } 
} 

배열을 수동으로 반복하고 일치하는 항목을 검색 할 수 있습니다.

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

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.

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=[];
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.

I'm not sure if PHP has a more efficient way to generate $CaseMap in the case where I'n not already using foreach.


I just had same problem and I could not change original array. I use few array functions for it.

Parameters

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

Solution

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

Make it shorter

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

I know this is old, but in case anyone else needs a quick easy way to do this without actually changing the original array:

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

참고URL : https://stackoverflow.com/questions/4240001/php-array-keys-case-insensitive-lookup

반응형