How to use complex object as keys in associative arrays in PHP?
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
add a comment |
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
That because the$a
and$b
are not the same (notice that$a !== $b
as you mention) - so they not represent same key on theSplObjectStorage
- 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
add a comment |
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
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
php associative-array
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 theSplObjectStorage
- 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
add a comment |
That because the$a
and$b
are not the same (notice that$a !== $b
as you mention) - so they not represent same key on theSplObjectStorage
- 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
add a comment |
2 Answers
2
active
oldest
votes
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.
Not sure it is more efficient than usingserialize
– 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
add a comment |
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Not sure it is more efficient than usingserialize
– 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
add a comment |
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.
Not sure it is more efficient than usingserialize
– 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
add a comment |
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.
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.
answered Nov 25 '18 at 13:56
Vaggelis KspsVaggelis Ksps
19119
19119
Not sure it is more efficient than usingserialize
– 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
add a comment |
Not sure it is more efficient than usingserialize
– 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
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 25 '18 at 17:59
nowoxnowox
6,208932102
6,208932102
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
That because the
$a
and$b
are not the same (notice that$a !== $b
as you mention) - so they not represent same key on theSplObjectStorage
- 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