Хорошо, поэтому у меня было другое решение (которое постоянно разрушает входной массив), кажется примерно на 30% быстрее, чем OP. Но затем я рассмотрел решение Найджела Рена, и тот управляет ими всеми.
РЕДАКТИРОВАТЬ: За исключением того, что решение Рена имеет одну оговорку. Он не работает с не скалярами, потому что он использует значения в качестве ключей массива. В то время как OP и мои решения так и делают (если мы настроим вызов array_keys со строгим = true, меня удивит то, что при строгом = true он станет несколько медленнее ???).
<?php
function solution(array $A) {
foreach ($A as $key => $value) {
$searchResults = array_keys($A, $value, true);
//print "Total number of $value found in Array is: " . count($searchResults) . "\n";
$checkNumber = count($searchResults);
if ($checkNumber == 1) {
//print "Unique value is: $value\n";
return $value;
}
//print "\n";
}
return null;
}
function solutionRen($a) {
$counts = @array_count_values($a); //disable warning when running over nonscalars
foreach ( $counts as $value => $count ) {
if ( $count == 1 ) {
return $value;
}
}
return false;
}
function solutionSlepic(array $A)
{
while (!empty($A)) {
$value = \array_shift($A);
$keys = \array_keys($A, $value, true);
if (empty($keys)) {
return $value;
}
foreach ($keys as $key) {
unset($A[$key]);
}
}
return null;
}
$range = \range(1,20000);
$input = \array_merge($range, $range, [1000001]);
$input = \array_merge([1000001], $range, $range);
$input = \array_merge($range, $range);
$input = \array_merge(\array_fill(0, 20000, 1), \array_fill(0, 20000, 2));
$input = [];
for($i=0; $i<20000; ++$i) {
$input[$i] = $input[20000 + $i] = new \stdClass();
}
$input[] = (object) ['unique' => true];
$start = \microtime(true);
$solutionOP = solution($input);
$timeOP = \microtime(true) - $start;
echo "OP: $solutionOP ({$timeOP})\n";
$start = \microtime(true);
$solutionRen = solutionRen($input);
$timeRen = \microtime(true) - $start;
echo "Ren: $solutionRen ({$timeRen})\n";
$start = \microtime(true);
$solutionSlepic = solutionSlepic($input);
$timeSlepic = \microtime(true) - $start;
echo "slepic: $solutionSlepic ({$timeSlepic})\n";
Выходы для различных входов:
// unnique valus is on end
OP: 1000001 (1.7094209194183)
Ren: 1000001 (0.00097393989562988)
slepic: 1000001 (1.1519079208374)
// unique value is the first
OP: 1000001 (0.00011515617370605)
Ren: 1000001 (0.0009620189666748)
slepic: 1000001 (0.00069785118103027)
// unique value not found among 20k distinct values, each twice in the set
OP: (1.728000164032)
Ren: (0.00064802169799805)
slepic: (1.18425989151)
// unque value not found among 2 distinct values, each 20k times in the set
OP: (6.4909980297089)
Ren: (0.00011396408081055)
slepic: (0.0016219615936279)
// 20000 distinct objects, each twice in the array and one unique on end
OP: (4.8111519813538)
stdClass Object
(
[unique] => 1
)
// Ren's solution is not capable of working with types other then those that can be keys of array, and so it didnt find the solution and instead yells 40k php warning which i have muted.
Ren: (0.013867139816284)
slepic: (2.5294151306152)
stdClass Object
(
[unique] => 1
)