PHP에 Java HashMap에 해당하는 것이 있습니까?


79

Java의 HashMap과 유사한 PHP 개체가 필요하지만 Google에서 찾지 못했기 때문에 누군가가 PHP에서 HashMaps를 모방하는 방법을 알고 있다면 도움을 주시면 감사하겠습니다.


1
해시 맵의 특징은 무엇입니까?
Felix Kling 2011-07-27

1
키 / 값 쌍이 필요하고 맵에서 배열로 키를 가져와야합니다.
newbie

1
$keys = array_keys($array);(또한 sushils 아래 답변을 참조)
KingCrunch

배열은 실제로 PHP에서 유일한 데이터 구조입니다 (클래스 / 객체를 데이터 구조로 간주하지 않는 경우). 키 / 값 구조를 제공하며 array_keys. 원한다면 래퍼 클래스를 작성할 수 있습니다.
Felix Kling 2011-07-27

답변:


95

PHP의 배열은 키 값 구조를 가질 수 있습니다.


64
@Gabi는 : 그것이 오리, 오리처럼 수영처럼 걷고 오리처럼 꽥꽥 경우 ... PHP 설명서는 말한다 : PHP의 배열이 실제로 정렬 된 맵입니다.
Felix Kling 2011-07-27

115
@Felix 클링 AFAIK PHP 어레이 O가없는 1 조회 / 삽입 / 삭제, 그들은하지 돌팔이 HashMaps을 같이 할 수 있도록
가비 Purcaru

14

20
@Gabi : PHP에서 배열의 내부 구현 해시 맵입니다.
KingCrunch

4
객체를 키로 사용할 수 없기 때문에 여전히 HashMap이 아닙니다. :(.
knub

37

원하는 것에 따라 SPL Object Storage 클래스에 관심이있을 수 있습니다.

http://php.net/manual/en/class.splobjectstorage.php

객체를 키로 사용할 수 있고, 계산할 인터페이스가 있고, 해시 및 기타 장점을 얻을 수 있습니다.

$s = new SplObjectStorage;
$o1 = new stdClass;
$o2 = new stdClass;
$o2->foo = 'bar';

$s[$o1] = 'baz';
$s[$o2] = 'bingo';

echo $s[$o1]; // 'baz'
echo $s[$o2]; // 'bingo'

2
이. boztek 당신은 과소 평가됩니다
CommaToast

SplObjectStorage에는 몇 가지 단점이 있습니다. foreach를 사용할 때 키는 정수입니다. 그리고 여기에서 키와 값 목록을 검색 할 수 없습니다. 제 경우에는 ArrayAccess, Iterator 및 Countable을 구현하는 사용자 정의 클래스를 사용하기로 결정했습니다.
carlosvini

@carlosvini 실제로 수행 할 수 있습니다 php.net/manual/en/class.splobjectstorage.php#114059
Olim 사이 도프에게

여기에 가장 좋은 대답
올렉 Abrazhaev

33

O (1) 읽기 복잡성으로 PHP에서 HashMap과 같은 Java를 만듭니다.

phpsh 터미널을 엽니 다.

php> $myhashmap = array();
php> $myhashmap['mykey1'] = 'myvalue1';
php> $myhashmap['mykey2'] = 'myvalue2';
php> echo $myhashmap['mykey2'];
myvalue2

$myhashmap['mykey2']이 경우 의 복잡도는 일정한 시간 O (1)으로 보입니다. 즉, $ myhasmap의 크기가 무한대에 가까워 질 때 키가 주어진 값을 검색하는 데 걸리는 시간은 동일하게 유지됩니다.

읽은 PHP 배열이 일정한 시간이라는 증거 :

PHP 인터프리터를 통해 실행하십시오.

php> for($x = 0; $x < 1000000000; $x++){
 ... $myhashmap[$x] = $x . " derp";
 ... }

루프는 10 억 개의 키 / 값을 추가하며, 메모리를 모두 소모 할 수있는 해시 맵에 모두 추가하는 데 약 2 분이 걸립니다.

그런 다음 조회하는 데 걸리는 시간을 확인하세요.

php> system('date +%N');echo "  " . $myhashmap[10333] . "  ";system('date +%N');
786946389  10333 derp  789008364

그렇다면 PHP 배열 맵 조회는 얼마나 빠릅니까?

10333우리가 고개 열쇠입니다. 1 백만 나노초 == 1 밀리 초. 키에서 값을 가져 오는 데 걸리는 시간은 206 만 나노초 또는 약 2 밀리 초입니다. 배열이 비어있는 경우 거의 같은 시간입니다. 이것은 나에게 일정한 시간처럼 보입니다.


일정한 시간이 아님 ... 기본 구현이 배열 기반 해시 맵이라고 가정하면 충돌을 처리 할 필요가 있기 때문에 충돌이 자체 균형으로 저장되는 경우 O (log n)를 수행 할 수 있습니다. 트리 (예 : 해시 맵의 Java 구현), 연결 목록 (체인)에 저장 될 수도 있습니다. 이는 최악의 경우 O (n)을 제공합니다. 이 ... 모두 삽입 마찬가지입니다 및 조회, 그러나 평균의 경우는 O (1)에 근접 할 것이다
다니엘 Valland

1
한 컴퓨터의 전체 메모리 (예 : 8GB)를 사용하는 데이터 세트 크기의 경우 조회 시간은 몇 밀리 초입니다. 그래서 그것은 "정확한 시간에 너무 가깝기 때문에 기본적으로 일정한 시간입니다"입니다.하지만 당신이 수학적으로 100 억 상자를 무한대로 수행하는 것을 올바르게 수행하고 싶다면 그것은 O (n log n)입니다. 나도 nitpick 수 있습니다. :) 나는 여기서 일정한 시간을 사용한다는 것은 "이건 병목 현상이되지 않을 것입니다.
Eric

모든 작업에 대한 O (log n)가 여전히 매우 빠르기 때문에 아마도 병목 현상이 아닐 것이라는 데 동의합니다. 요점은 일정한 시간 해싱을 얻는 유일한 방법은 해시 함수가 완벽하고 충돌이 존재할 수없는 경우입니다. 완벽하지 않다면 가장 좋은 것은 O (log n)입니다. 그러나 phpinternalsbook.com/hashtables/basic_structure.html 에 따르면 php는 최악의 경우 O (N) 인 체인을 사용합니다. 나는 자기 균형 트리와 같이 log n을 달성하는 솔루션이 사용될 것으로 기대하기 때문에 그것이 사실인지 모르겠지만, 그렇다면 O (N)과 O (1) )은 사소하지 않습니다.
Daniel Valland

16
$fruits = array (
    "fruits"  => array("a" => "Orange", "b" => "Banana", "c" => "Apple"),
    "numbers" => array(1, 2, 3, 4, 5, 6),
    "holes"   => array("first", 5 => "second", "third")
);

echo $fruits["fruits"]["b"]

'바나나'출력

http://in2.php.net/manual/en/function.array.php 에서 가져온


빈 배열 을 선언하고 "fruits" => array("a" => "Orange", "b" => "Banana", "c" => "Apple")다음 과 같이 할당하려면 어떻게해야 합니까?
diegoaguilar

2
@Diego $fruits = array(); $fruits['fruits'] = array('a' => 'Orange',...);... 실제로이 작업을 즉시 수행 할 수도 있습니다. .NET Framework $fruits['fruits']['a'] = 'Orange'; $fruits['holes']['first'] = 5; $fruits['numbers'][] = 1;를 사용하여 배열을 반드시 만들 필요도 없습니다 array().
zamnuts

10

O (1) 읽기 복잡성 (자신의 해시 함수의 품질에 따라 다름)이있는 문자열 및 정수 이외의 키로도 작동하는 HashMap.

간단한 hashMap을 직접 만들 수 있습니다. hashMap이하는 일은 해시를 인덱스 / 키로 사용하여 배열에 항목을 저장하는 것입니다. 해시 함수는 가끔 충돌을 제공하므로 (자주하지는 않지만 발생할 수 있음) hashMap의 항목에 대해 여러 항목을 저장해야합니다. 그 간단한 것은 hashMap입니다.

class IEqualityComparer {
    public function equals($x, $y) {
        throw new Exception("Not implemented!");
    }
    public function getHashCode($obj) {
        throw new Exception("Not implemented!");
    }
}

class HashMap {
    private $map = array();
    private $comparer;

    public function __construct(IEqualityComparer $keyComparer) {
        $this->comparer = $keyComparer;
    }

    public function has($key) {
        $hash = $this->comparer->getHashCode($key);

        if (!isset($this->map[$hash])) {
            return false;
        }

        foreach ($this->map[$hash] as $item) {
            if ($this->comparer->equals($item['key'], $key)) {
                return true;
            }
        }

        return false;
    }

    public function get($key) {
        $hash = $this->comparer->getHashCode($key);

        if (!isset($this->map[$hash])) {
            return false;
        }

        foreach ($this->map[$hash] as $item) {
            if ($this->comparer->equals($item['key'], $key)) {
                return $item['value'];
            }
        }

        return false;
    }

    public function del($key) {
        $hash = $this->comparer->getHashCode($key);

        if (!isset($this->map[$hash])) {
            return false;
        }

        foreach ($this->map[$hash] as $index => $item) {
            if ($this->comparer->equals($item['key'], $key)) {
                unset($this->map[$hash][$index]);
                if (count($this->map[$hash]) == 0)
                    unset($this->map[$hash]);

                return true;
            }
        }

        return false;
    }

    public function put($key, $value) {
        $hash = $this->comparer->getHashCode($key);

        if (!isset($this->map[$hash])) {
            $this->map[$hash] = array();
        }

        $newItem = array('key' => $key, 'value' => $value);        

        foreach ($this->map[$hash] as $index => $item) {
            if ($this->comparer->equals($item['key'], $key)) {
                $this->map[$hash][$index] = $newItem;
                return;
            }
        }

        $this->map[$hash][] = $newItem;
    }
}

그것이 작동하려면 키에 대한 해시 함수와 동등성을위한 비교자가 필요합니다 (항목이 몇 개만 있거나 다른 이유로 속도가 필요하지 않은 경우 해시 함수가 0을 반환하도록 할 수 있습니다. 모든 항목은 동일한 버킷에 넣으면 O (N) 복잡성이 발생합니다)

다음은 그 예입니다.

class IntArrayComparer extends IEqualityComparer {
    public function equals($x, $y) {
        if (count($x) !== count($y))
            return false;

        foreach ($x as $key => $value) {
            if (!isset($y[$key]) || $y[$key] !== $value)
                return false;
        }

        return true;
    }

    public function getHashCode($obj) {
        $hash = 0;
        foreach ($obj as $key => $value)
            $hash ^= $key ^ $value;

        return $hash;
    }
}

$hashmap = new HashMap(new IntArrayComparer());

for ($i = 0; $i < 10; $i++) {
    for ($j = 0; $j < 10; $j++) {
        $hashmap->put(array($i, $j), $i * 10 + $j);
    }
}

echo $hashmap->get(array(3, 7)) . "<br/>";
echo $hashmap->get(array(5, 1)) . "<br/>";

echo ($hashmap->has(array(8, 4))? 'true': 'false') . "<br/>";
echo ($hashmap->has(array(-1, 9))? 'true': 'false') . "<br/>";
echo ($hashmap->has(array(6))? 'true': 'false') . "<br/>";
echo ($hashmap->has(array(1, 2, 3))? 'true': 'false') . "<br/>";

$hashmap->del(array(8, 4));
echo ($hashmap->has(array(8, 4))? 'true': 'false') . "<br/>";

출력으로 제공됩니다.

37
51
true
false
false
false
false

3
IEqualityComparer해야합니다 interface여기에
vp_arth

0

php에서 사용자 정의 HashMap 클래스를 만들 수 있습니다. get 및 set과 같은 기본 HashMap 속성을 포함하는 아래 표시된 예제.

class HashMap{

        public $arr;

        function init() {

            function populate() {
                return null;
            }
            
            // change to 999 for efficiency
            $this->arr = array_map('populate', range(0, 9));

            return $this->arr;

        }
        
        function get_hash($key) {
            $hash = 0;

            for ($i=0; $i < strlen($key) ; $i++) { 
                $hash += ord($key[$i]);
            }
            
            // arr index starts from 0
            $hash_idx = $hash % (count($this->arr) - 1); 
            return $hash_idx;
            
        }

        function add($key, $value) {
            $idx = $this->get_hash($key);
            
            if ($this->arr[$idx] == null) {
                $this->arr[$idx] = [$value];
            } else{

                $found = false;

                $content = $this->arr[$idx];
                
                $content_idx = 0;
                foreach ($content as $item) {

                    // checking if they have same number of streams
                    if ($item == $value) {

                        $content[$content_idx] = [$value];
                        $found = true;
                        break;

                    }
                    
                    $content_idx++;
                }

                if (!$found) {
                    // $value is already an array
                    array_push($content, $value);

                    // updating the array
                    $this->arr[$idx] = $content;
                }

            }

            return $this->arr;

        }

        function get($key) {

            $idx = $this->get_hash($key);
            $content = $this->arr[$idx];

            foreach ($content as $item) {
                if ($item[1] == $key) {
                    return $item;
                    break;
                }
            }
                
        }

    }

이것이 도움이 되었기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.