You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
array_unique: add way to compare items with an identity check (===) #10526
changed the title [-]array_unique: Implicit type-casting is performed in spite of the `SORT_REGULAR` flag[/-][+]array_unique: add way to compare items with an identity check (``===``)[/+]on Feb 7, 2023
I just wonder what the behaviour should be in case someone decides to use this new flag in sorting and the values aren't comparable because they are of different types. An exception maybe? But then again that's probably a bit strange because array_unique wouldn't have this issue.
I just wonder what the behaviour should be in case someone decides to use this new flag in sorting and the values aren't comparable because they are of different types. An exception maybe? But then again that's probably a bit strange because array_unique wouldn't have this issue.
New sorting method have to sort by type first, because array_unique is relaying on consistent comparisons for optimization, so if used in sort it would sort by types then values - probably useless but would work fine.
Thus new method would look something like this:
functioncmp_strict(mixed$a, mixed$b): int
{
if ($a === $b) return0;
$typeA = gettype($a);
$typeB = gettype($b);
if ($typeA === $typeB) {
// abstract function to compare values without type jugglingreturncmp_values_strict($a, $b);
} else {
return$typeA <=> $typeB;
}
}
Therefore, changing this to a feature request, by possibly introducing a new flag.
As with sort functions, array_unique could allow use of custom comparison function to cover more complex cases (e.g. when multiple values have same meaning), though flag would be more convenient in almost every case.
Err wait... The example code of a comparator posted here wouldn't work too... For example cmp_strict(0, '0') would cause the branch with the spaceship operator to be executed, which results in a return value of 0. This means that array_unique would remove on of the two, which is the exact problem in this issue report.
The main problem is that there seems to be no total order relation on elements of all sorts of different type combinations. For example: is '0'<0, or is 0<'0'? If both answers are yes then we have an inconsistency in sorting. If both answers are no then they must be equal, which causes OP's problem. In other cases the ordering is arbitrary.
So although this issue proposes to add a new flag, we cannot use that flag in a consistent way for sorting. The flag would be unique to array_unique and must be handled in a special way AFAICT. Or we have to come up with an ordering scheme that works for all type combinations.
For example cmp_strict(0, '0') would cause the branch with the spaceship operator to be executed, which results in a return value of 0.
@nielsdos Branch with spaceship operator is only comparing types, which are always string and always starting with letter, so it's safe comparison. https://3v4l.org/jnLno
For example: is '0'<0, or is 0<'0'?
"integer" < "string" thus 0<'0'.
So although this issue proposes to add a new flag, we cannot use that flag in a consistent way for sorting.
Sorting by type first is consistent way of sorting, not sure if should be allowed in sort, but won't hurt anything.
Or we have to come up with an ordering scheme that works for all type combinations.
Comparing types first should be faster for mixed arrays, which is ideal for array_unique.
@KapitanOczywisty Sorry, my bad, I misread the code. So the solution here is the "arbitrary order" option I listed which seems not super arbitrary after all since it seems to be consistent with zend_compare. I'll try this tomorrow.
Activity
Girgias commentedon Feb 7, 2023
This is the expected behaviour, as
SORT_REGULARuses==under the hood.From the
sort()page (which has a better description thenarray_unique())Therefore, changing this to a feature request, by possibly introducing a new flag.
[-]array_unique: Implicit type-casting is performed in spite of the `SORT_REGULAR` flag[/-][+]array_unique: add way to compare items with an identity check (``===``)[/+]ndossche commentedon Feb 7, 2023
I just wonder what the behaviour should be in case someone decides to use this new flag in sorting and the values aren't comparable because they are of different types. An exception maybe? But then again that's probably a bit strange because array_unique wouldn't have this issue.
blar commentedon Feb 7, 2023
Should the default behaviour of
array_uniqdepend ondeclare(strict_types = 1)?damianwadley commentedon Feb 7, 2023
strict_typesis about function arguments at call time. It shouldn't control runtime behavior this way.KapitanOczywisty commentedon Feb 8, 2023
New sorting method have to sort by type first, because
array_uniqueis relaying on consistent comparisons for optimization, so if used in sort it would sort by types then values - probably useless but would work fine.Thus new method would look something like this:
As with sort functions,
array_uniquecould allow use of custom comparison function to cover more complex cases (e.g. when multiple values have same meaning), though flag would be more convenient in almost every case.ndossche commentedon Feb 8, 2023
Thanks for pointing that out, it looks indeed like a logical comparison function. I can spend some time this week to try and implement a PoC.
ndossche commentedon Feb 10, 2023
Err wait... The example code of a comparator posted here wouldn't work too... For example
cmp_strict(0, '0')would cause the branch with the spaceship operator to be executed, which results in a return value of 0. This means that array_unique would remove on of the two, which is the exact problem in this issue report.The main problem is that there seems to be no total order relation on elements of all sorts of different type combinations. For example: is '0'<0, or is 0<'0'? If both answers are yes then we have an inconsistency in sorting. If both answers are no then they must be equal, which causes OP's problem. In other cases the ordering is arbitrary.
So although this issue proposes to add a new flag, we cannot use that flag in a consistent way for sorting. The flag would be unique to array_unique and must be handled in a special way AFAICT. Or we have to come up with an ordering scheme that works for all type combinations.
KapitanOczywisty commentedon Feb 10, 2023
@nielsdos Branch with spaceship operator is only comparing types, which are always string and always starting with letter, so it's safe comparison. https://3v4l.org/jnLno
"integer" < "string" thus 0<'0'.
Sorting by type first is consistent way of sorting, not sure if should be allowed in sort, but won't hurt anything.
Comparing types first should be faster for mixed arrays, which is ideal for
array_unique.This is a bit closer to proper implementation: https://3v4l.org/2oRQt
ndossche commentedon Feb 10, 2023
@KapitanOczywisty Sorry, my bad, I misread the code. So the solution here is the "arbitrary order" option I listed which seems not super arbitrary after all since it seems to be consistent with
zend_compare. I'll try this tomorrow.Implement phpGH-10526: array_unique: add way to compare items with an…
iluuu1994 commentedon Mar 23, 2023
This is essentially the same as #9775, so I'm closing this as a duplicate. Please continue discussion there if you have anything to add.