How to use complex object as keys in associative arrays in PHP?












0















I would like to get values for a collection of values:



>>> class Foo() {}
>>> $v = (object)[42];

>>> $a = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]
>>> $b = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]

>>> $data[$a] = 42;
>>> echo $data[$b]
42


I tried with SplObjectStorage, but I need to convert $a into an object and in this case $a != $b because they are different instances:



$s = new SplObjectStorage()
$s[$a] = 42
echo $s[$b]
UnexpectedValueException with message 'Object not found'


How can I achieve this in PHP?



In Python I would have used:



>>> a = (1, 1, 2, 3, 5, Foo, 'o_o', hashable_object)
>>> b = (1, 1, 2, 3, 5, Foo, 'o_o', hashable_object)
>>> data[a] = 42
>>> print(data[b])
42


EDIT



One not very efficient working solution would be:



>>> class Foo() {}
>>> $v = (object)[42];

>>> $a = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]
>>> $b = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]

>>> $data[serialize($a)] = 42;
>>> echo $data[serialize($b)]
42









share|improve this question

























  • That because the $a and $b are not the same (notice that $a !== $b as you mention) - so they not represent same key on the SplObjectStorage - so I guess it is the expected output

    – dWinder
    Nov 25 '18 at 13:45











  • Indeed, it is the expected output, but I don't know how to answer the question though.

    – nowox
    Nov 25 '18 at 13:45











  • Why do you think it is not efficient?

    – revo
    Nov 25 '18 at 15:10
















0















I would like to get values for a collection of values:



>>> class Foo() {}
>>> $v = (object)[42];

>>> $a = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]
>>> $b = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]

>>> $data[$a] = 42;
>>> echo $data[$b]
42


I tried with SplObjectStorage, but I need to convert $a into an object and in this case $a != $b because they are different instances:



$s = new SplObjectStorage()
$s[$a] = 42
echo $s[$b]
UnexpectedValueException with message 'Object not found'


How can I achieve this in PHP?



In Python I would have used:



>>> a = (1, 1, 2, 3, 5, Foo, 'o_o', hashable_object)
>>> b = (1, 1, 2, 3, 5, Foo, 'o_o', hashable_object)
>>> data[a] = 42
>>> print(data[b])
42


EDIT



One not very efficient working solution would be:



>>> class Foo() {}
>>> $v = (object)[42];

>>> $a = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]
>>> $b = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]

>>> $data[serialize($a)] = 42;
>>> echo $data[serialize($b)]
42









share|improve this question

























  • That because the $a and $b are not the same (notice that $a !== $b as you mention) - so they not represent same key on the SplObjectStorage - so I guess it is the expected output

    – dWinder
    Nov 25 '18 at 13:45











  • Indeed, it is the expected output, but I don't know how to answer the question though.

    – nowox
    Nov 25 '18 at 13:45











  • Why do you think it is not efficient?

    – revo
    Nov 25 '18 at 15:10














0












0








0








I would like to get values for a collection of values:



>>> class Foo() {}
>>> $v = (object)[42];

>>> $a = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]
>>> $b = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]

>>> $data[$a] = 42;
>>> echo $data[$b]
42


I tried with SplObjectStorage, but I need to convert $a into an object and in this case $a != $b because they are different instances:



$s = new SplObjectStorage()
$s[$a] = 42
echo $s[$b]
UnexpectedValueException with message 'Object not found'


How can I achieve this in PHP?



In Python I would have used:



>>> a = (1, 1, 2, 3, 5, Foo, 'o_o', hashable_object)
>>> b = (1, 1, 2, 3, 5, Foo, 'o_o', hashable_object)
>>> data[a] = 42
>>> print(data[b])
42


EDIT



One not very efficient working solution would be:



>>> class Foo() {}
>>> $v = (object)[42];

>>> $a = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]
>>> $b = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]

>>> $data[serialize($a)] = 42;
>>> echo $data[serialize($b)]
42









share|improve this question
















I would like to get values for a collection of values:



>>> class Foo() {}
>>> $v = (object)[42];

>>> $a = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]
>>> $b = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]

>>> $data[$a] = 42;
>>> echo $data[$b]
42


I tried with SplObjectStorage, but I need to convert $a into an object and in this case $a != $b because they are different instances:



$s = new SplObjectStorage()
$s[$a] = 42
echo $s[$b]
UnexpectedValueException with message 'Object not found'


How can I achieve this in PHP?



In Python I would have used:



>>> a = (1, 1, 2, 3, 5, Foo, 'o_o', hashable_object)
>>> b = (1, 1, 2, 3, 5, Foo, 'o_o', hashable_object)
>>> data[a] = 42
>>> print(data[b])
42


EDIT



One not very efficient working solution would be:



>>> class Foo() {}
>>> $v = (object)[42];

>>> $a = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]
>>> $b = [1, 1, 2, 3, 5, Foo::class, 'o_o', $v]

>>> $data[serialize($a)] = 42;
>>> echo $data[serialize($b)]
42






php associative-array






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 25 '18 at 13:29







nowox

















asked Nov 25 '18 at 13:21









nowoxnowox

6,208932102




6,208932102













  • That because the $a and $b are not the same (notice that $a !== $b as you mention) - so they not represent same key on the SplObjectStorage - so I guess it is the expected output

    – dWinder
    Nov 25 '18 at 13:45











  • Indeed, it is the expected output, but I don't know how to answer the question though.

    – nowox
    Nov 25 '18 at 13:45











  • Why do you think it is not efficient?

    – revo
    Nov 25 '18 at 15:10



















  • That because the $a and $b are not the same (notice that $a !== $b as you mention) - so they not represent same key on the SplObjectStorage - so I guess it is the expected output

    – dWinder
    Nov 25 '18 at 13:45











  • Indeed, it is the expected output, but I don't know how to answer the question though.

    – nowox
    Nov 25 '18 at 13:45











  • Why do you think it is not efficient?

    – revo
    Nov 25 '18 at 15:10

















That because the $a and $b are not the same (notice that $a !== $b as you mention) - so they not represent same key on the SplObjectStorage - so I guess it is the expected output

– dWinder
Nov 25 '18 at 13:45





That because the $a and $b are not the same (notice that $a !== $b as you mention) - so they not represent same key on the SplObjectStorage - so I guess it is the expected output

– dWinder
Nov 25 '18 at 13:45













Indeed, it is the expected output, but I don't know how to answer the question though.

– nowox
Nov 25 '18 at 13:45





Indeed, it is the expected output, but I don't know how to answer the question though.

– nowox
Nov 25 '18 at 13:45













Why do you think it is not efficient?

– revo
Nov 25 '18 at 15:10





Why do you think it is not efficient?

– revo
Nov 25 '18 at 15:10












2 Answers
2






active

oldest

votes


















1














According to php manual arrays and objects cannot be used as array keys.



What you could do is this:



>>> class Foo {}
>>> $test = new stdClass();
>>> $test->{implode([1, 1, 2, 3, 5, Foo::class, 'o_o'])} = 42;
>>> $test->{implode([1, 1, 2, 3, 5, Foo::class, 'o_o'])};
=> 42


What i was going to do is this:



$test->something = [ 42 => [1, 1, 2, 3, 5, Foo::class, 'o_o']];
array_search([1, 1, 2, 3, 5, Foo::class, 'o_o'], $test->something, true);
=> 42


I hope it helps.






share|improve this answer
























  • Not sure it is more efficient than using serialize

    – nowox
    Nov 25 '18 at 13:57






  • 1





    According @Peon 's comment here Implode 2 elements: 1.8937180042267 seconds, Implode 4 elements: 2.4380650520325 seconds, Implode 8 elements: 3.6058769226074 seconds Not exactly two times, but close to it, while serialize changes with the same progression type, but slower rate. So i think serialize is faster and it is up to you man and always add the full path of the function for better performance. For example array_search()

    – Vaggelis Ksps
    Nov 25 '18 at 14:05





















0














By looking at the PHP doc I found 'DsMap' available from PECL. With this you can write:



$map = new DsMap();

$v = (object)[41];

$a = [1, 1, 2, 3, 5, 'o_o', $v];
$b = [1, 1, 2, 3, 5, 'o_o', $v];

$map[$a] = 42;

var_dump($map[$b]);


I also looked at the implementation:



https://github.com/php-ds/ext-ds/blob/master/src/ds/ds_htable.c



The zval is hashed with this function



static uint32_t get_array_hash(zval *array)
{
uint32_t hash;
php_serialize_data_t var_hash;
smart_str buffer = {0};

PHP_VAR_SERIALIZE_INIT(var_hash);
php_var_serialize(&buffer, array, &var_hash);
PHP_VAR_SERIALIZE_DESTROY(var_hash);

smart_str_0(&buffer);

if (buffer.s) {
hash = get_string_hash(buffer.s);
zend_string_free(buffer.s);
} else {
hash = 0;
}

return hash;
}


So behind the scene it is the serialize function that is used. I feel a bit sad about this. So your inefficient function will be not much inefficient at the end.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53467894%2fhow-to-use-complex-object-as-keys-in-associative-arrays-in-php%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    According to php manual arrays and objects cannot be used as array keys.



    What you could do is this:



    >>> class Foo {}
    >>> $test = new stdClass();
    >>> $test->{implode([1, 1, 2, 3, 5, Foo::class, 'o_o'])} = 42;
    >>> $test->{implode([1, 1, 2, 3, 5, Foo::class, 'o_o'])};
    => 42


    What i was going to do is this:



    $test->something = [ 42 => [1, 1, 2, 3, 5, Foo::class, 'o_o']];
    array_search([1, 1, 2, 3, 5, Foo::class, 'o_o'], $test->something, true);
    => 42


    I hope it helps.






    share|improve this answer
























    • Not sure it is more efficient than using serialize

      – nowox
      Nov 25 '18 at 13:57






    • 1





      According @Peon 's comment here Implode 2 elements: 1.8937180042267 seconds, Implode 4 elements: 2.4380650520325 seconds, Implode 8 elements: 3.6058769226074 seconds Not exactly two times, but close to it, while serialize changes with the same progression type, but slower rate. So i think serialize is faster and it is up to you man and always add the full path of the function for better performance. For example array_search()

      – Vaggelis Ksps
      Nov 25 '18 at 14:05


















    1














    According to php manual arrays and objects cannot be used as array keys.



    What you could do is this:



    >>> class Foo {}
    >>> $test = new stdClass();
    >>> $test->{implode([1, 1, 2, 3, 5, Foo::class, 'o_o'])} = 42;
    >>> $test->{implode([1, 1, 2, 3, 5, Foo::class, 'o_o'])};
    => 42


    What i was going to do is this:



    $test->something = [ 42 => [1, 1, 2, 3, 5, Foo::class, 'o_o']];
    array_search([1, 1, 2, 3, 5, Foo::class, 'o_o'], $test->something, true);
    => 42


    I hope it helps.






    share|improve this answer
























    • Not sure it is more efficient than using serialize

      – nowox
      Nov 25 '18 at 13:57






    • 1





      According @Peon 's comment here Implode 2 elements: 1.8937180042267 seconds, Implode 4 elements: 2.4380650520325 seconds, Implode 8 elements: 3.6058769226074 seconds Not exactly two times, but close to it, while serialize changes with the same progression type, but slower rate. So i think serialize is faster and it is up to you man and always add the full path of the function for better performance. For example array_search()

      – Vaggelis Ksps
      Nov 25 '18 at 14:05
















    1












    1








    1







    According to php manual arrays and objects cannot be used as array keys.



    What you could do is this:



    >>> class Foo {}
    >>> $test = new stdClass();
    >>> $test->{implode([1, 1, 2, 3, 5, Foo::class, 'o_o'])} = 42;
    >>> $test->{implode([1, 1, 2, 3, 5, Foo::class, 'o_o'])};
    => 42


    What i was going to do is this:



    $test->something = [ 42 => [1, 1, 2, 3, 5, Foo::class, 'o_o']];
    array_search([1, 1, 2, 3, 5, Foo::class, 'o_o'], $test->something, true);
    => 42


    I hope it helps.






    share|improve this answer













    According to php manual arrays and objects cannot be used as array keys.



    What you could do is this:



    >>> class Foo {}
    >>> $test = new stdClass();
    >>> $test->{implode([1, 1, 2, 3, 5, Foo::class, 'o_o'])} = 42;
    >>> $test->{implode([1, 1, 2, 3, 5, Foo::class, 'o_o'])};
    => 42


    What i was going to do is this:



    $test->something = [ 42 => [1, 1, 2, 3, 5, Foo::class, 'o_o']];
    array_search([1, 1, 2, 3, 5, Foo::class, 'o_o'], $test->something, true);
    => 42


    I hope it helps.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 25 '18 at 13:56









    Vaggelis KspsVaggelis Ksps

    19119




    19119













    • Not sure it is more efficient than using serialize

      – nowox
      Nov 25 '18 at 13:57






    • 1





      According @Peon 's comment here Implode 2 elements: 1.8937180042267 seconds, Implode 4 elements: 2.4380650520325 seconds, Implode 8 elements: 3.6058769226074 seconds Not exactly two times, but close to it, while serialize changes with the same progression type, but slower rate. So i think serialize is faster and it is up to you man and always add the full path of the function for better performance. For example array_search()

      – Vaggelis Ksps
      Nov 25 '18 at 14:05





















    • Not sure it is more efficient than using serialize

      – nowox
      Nov 25 '18 at 13:57






    • 1





      According @Peon 's comment here Implode 2 elements: 1.8937180042267 seconds, Implode 4 elements: 2.4380650520325 seconds, Implode 8 elements: 3.6058769226074 seconds Not exactly two times, but close to it, while serialize changes with the same progression type, but slower rate. So i think serialize is faster and it is up to you man and always add the full path of the function for better performance. For example array_search()

      – Vaggelis Ksps
      Nov 25 '18 at 14:05



















    Not sure it is more efficient than using serialize

    – nowox
    Nov 25 '18 at 13:57





    Not sure it is more efficient than using serialize

    – nowox
    Nov 25 '18 at 13:57




    1




    1





    According @Peon 's comment here Implode 2 elements: 1.8937180042267 seconds, Implode 4 elements: 2.4380650520325 seconds, Implode 8 elements: 3.6058769226074 seconds Not exactly two times, but close to it, while serialize changes with the same progression type, but slower rate. So i think serialize is faster and it is up to you man and always add the full path of the function for better performance. For example array_search()

    – Vaggelis Ksps
    Nov 25 '18 at 14:05







    According @Peon 's comment here Implode 2 elements: 1.8937180042267 seconds, Implode 4 elements: 2.4380650520325 seconds, Implode 8 elements: 3.6058769226074 seconds Not exactly two times, but close to it, while serialize changes with the same progression type, but slower rate. So i think serialize is faster and it is up to you man and always add the full path of the function for better performance. For example array_search()

    – Vaggelis Ksps
    Nov 25 '18 at 14:05















    0














    By looking at the PHP doc I found 'DsMap' available from PECL. With this you can write:



    $map = new DsMap();

    $v = (object)[41];

    $a = [1, 1, 2, 3, 5, 'o_o', $v];
    $b = [1, 1, 2, 3, 5, 'o_o', $v];

    $map[$a] = 42;

    var_dump($map[$b]);


    I also looked at the implementation:



    https://github.com/php-ds/ext-ds/blob/master/src/ds/ds_htable.c



    The zval is hashed with this function



    static uint32_t get_array_hash(zval *array)
    {
    uint32_t hash;
    php_serialize_data_t var_hash;
    smart_str buffer = {0};

    PHP_VAR_SERIALIZE_INIT(var_hash);
    php_var_serialize(&buffer, array, &var_hash);
    PHP_VAR_SERIALIZE_DESTROY(var_hash);

    smart_str_0(&buffer);

    if (buffer.s) {
    hash = get_string_hash(buffer.s);
    zend_string_free(buffer.s);
    } else {
    hash = 0;
    }

    return hash;
    }


    So behind the scene it is the serialize function that is used. I feel a bit sad about this. So your inefficient function will be not much inefficient at the end.






    share|improve this answer




























      0














      By looking at the PHP doc I found 'DsMap' available from PECL. With this you can write:



      $map = new DsMap();

      $v = (object)[41];

      $a = [1, 1, 2, 3, 5, 'o_o', $v];
      $b = [1, 1, 2, 3, 5, 'o_o', $v];

      $map[$a] = 42;

      var_dump($map[$b]);


      I also looked at the implementation:



      https://github.com/php-ds/ext-ds/blob/master/src/ds/ds_htable.c



      The zval is hashed with this function



      static uint32_t get_array_hash(zval *array)
      {
      uint32_t hash;
      php_serialize_data_t var_hash;
      smart_str buffer = {0};

      PHP_VAR_SERIALIZE_INIT(var_hash);
      php_var_serialize(&buffer, array, &var_hash);
      PHP_VAR_SERIALIZE_DESTROY(var_hash);

      smart_str_0(&buffer);

      if (buffer.s) {
      hash = get_string_hash(buffer.s);
      zend_string_free(buffer.s);
      } else {
      hash = 0;
      }

      return hash;
      }


      So behind the scene it is the serialize function that is used. I feel a bit sad about this. So your inefficient function will be not much inefficient at the end.






      share|improve this answer


























        0












        0








        0







        By looking at the PHP doc I found 'DsMap' available from PECL. With this you can write:



        $map = new DsMap();

        $v = (object)[41];

        $a = [1, 1, 2, 3, 5, 'o_o', $v];
        $b = [1, 1, 2, 3, 5, 'o_o', $v];

        $map[$a] = 42;

        var_dump($map[$b]);


        I also looked at the implementation:



        https://github.com/php-ds/ext-ds/blob/master/src/ds/ds_htable.c



        The zval is hashed with this function



        static uint32_t get_array_hash(zval *array)
        {
        uint32_t hash;
        php_serialize_data_t var_hash;
        smart_str buffer = {0};

        PHP_VAR_SERIALIZE_INIT(var_hash);
        php_var_serialize(&buffer, array, &var_hash);
        PHP_VAR_SERIALIZE_DESTROY(var_hash);

        smart_str_0(&buffer);

        if (buffer.s) {
        hash = get_string_hash(buffer.s);
        zend_string_free(buffer.s);
        } else {
        hash = 0;
        }

        return hash;
        }


        So behind the scene it is the serialize function that is used. I feel a bit sad about this. So your inefficient function will be not much inefficient at the end.






        share|improve this answer













        By looking at the PHP doc I found 'DsMap' available from PECL. With this you can write:



        $map = new DsMap();

        $v = (object)[41];

        $a = [1, 1, 2, 3, 5, 'o_o', $v];
        $b = [1, 1, 2, 3, 5, 'o_o', $v];

        $map[$a] = 42;

        var_dump($map[$b]);


        I also looked at the implementation:



        https://github.com/php-ds/ext-ds/blob/master/src/ds/ds_htable.c



        The zval is hashed with this function



        static uint32_t get_array_hash(zval *array)
        {
        uint32_t hash;
        php_serialize_data_t var_hash;
        smart_str buffer = {0};

        PHP_VAR_SERIALIZE_INIT(var_hash);
        php_var_serialize(&buffer, array, &var_hash);
        PHP_VAR_SERIALIZE_DESTROY(var_hash);

        smart_str_0(&buffer);

        if (buffer.s) {
        hash = get_string_hash(buffer.s);
        zend_string_free(buffer.s);
        } else {
        hash = 0;
        }

        return hash;
        }


        So behind the scene it is the serialize function that is used. I feel a bit sad about this. So your inefficient function will be not much inefficient at the end.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 25 '18 at 17:59









        nowoxnowox

        6,208932102




        6,208932102






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53467894%2fhow-to-use-complex-object-as-keys-in-associative-arrays-in-php%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

            Calculate evaluation metrics using cross_val_predict sklearn

            Insert data from modal to MySQL (multiple modal on website)