Как вернуть элементы массива с наивысшими значениями?
В моем коде у меня есть два элемента, которые имеют одинаковый возраст "Joe"=>"43"
и "Rob"=>"43"
.
Мой вывод кода:
Джо
Я хочу вывести:
Джо и Роб
Потому что они имеют наибольшее значение.
Это мой код:
<?php
$cur = 1;
$age = array("Peter" => "35", "Ben" => "37", "Joe" => "43", "Rob" => "43");
$new_array = array();
arsort($age);
$new_array = $age;
$key = array_search(max($new_array), $new_array);
while ($cur > 0) {
echo $key;
$cur--;
}
?>
Ответы
Ответ 1
Я бы изменил ключи и значения в массиве, затем отсортировал по ключу и вернул значения первого ключа:
$ages = array("Peter" => "35", "Ben" => "37", "Joe" => "43", "Rob" => "43");
$new = array();
foreach ($ages as $name => $age) {
$new[$age][] = $name;
}
uksort($new, function($ka, $kb) { return $kb - $ka; }); // or just krsort($new);
$new = array_values($new)[0]; // <- to use this you have to have at least PHP 5.4
// if you have PHP < 5.4 you can simply do it in two steps:
// $new = array_values($new);
// $new = $new[0];
Посмотрите на действие!
EDIT: еще проще!
$ages = array("Peter" => "35", "Ben" => "37", "Joe" => "43", "Rob" => "43");
$max = max($ages);
$new = array_keys(array_filter($ages, function ($age) use ($max) { return $age == $max; }));
Ответ 2
Использование:
$people = array("Peter" => "35", "Ben" => "37", "Joe" => "43", "Rob" => "43");
$max = max($people);
$result = array_filter($people, function($age) use ($max){ return $max == $age; });
Результат:
Array
(
[Joe] => 43
[Rob] => 43
)
Ответ 3
Просто проверьте его вручную:
$age = array("Peter" => "35", "Ben" => "37", "Joe" => "43", "Rob" => "43");
$new_array = array();
arsort($age);
$new_array = $age;
$max = max($new_array);
$results = array();
foreach ($new_array as $key => $val) {
if ($val == $max) {
$results[] = $key;
}
}
echo implode(' and ', $results);
// will output "joe and bob"
Ответ 4
Мне нравится ответ @matteo-tassinari и @evilive гораздо больше и хотел предложить его сам. Но так как вопрос об эффективности пришел, вот решение, использующее только один цикл и поэтому имеющее линейную временную сложность:
<?php
$max = ~PHP_INT_MAX;
$result = [];
foreach($age as $key => $value) {
if($value > $max) {
$result = [ $key => $value ];
$max = $value;
}
if($value == $max) {
$result[$key] = $value;
}
}
var_dump($result);
И существует другое решение, которое использует сортировку ведра:
function bucket($ages) {
$buckets = [];
foreach($ages as $key => $value) {
$buckets[$value][] = $key;
}
return $buckets[max(array_keys($buckets))];
}
Что касается обсуждения эффективности и масштабируемости, я написал небольшой тест script для четырех видов предлагаемых решений (цикл, sort, , ковш):
<?php
function loop($ages) {
$max = 0;
$result = [];
foreach($ages as $key => $value) {
if($value > $max) {
$result = [ $key => $value ];
$max = $value;
}
if($value == $max) {
$result[$key] = $value;
}
}
return array_keys($result);
}
function filter($ages) {
$max = max($ages);
$new = array_filter($ages, function ($age) use ($max) { return $age == $max; });
return array_keys($new);
}
function bucket($ages) {
$buckets = [];
foreach($ages as $key => $value) {
$buckets[$value][] = $key;
}
return $buckets[max(array_keys($buckets))];
}
for($n = 2; $n < 10000000; $n*=2) {
$ages = [];
for($i = 0; $i < $n; $i++) {
$ages['name_'.$i] = rand(0,100);
}
$start = microtime(true);
echo $n.';';
loop($ages);
echo (microtime(true) - $start).';';
$start = microtime(true);
arsort($ages);
echo (microtime(true) - $start).';';
$start = microtime(true);
filter($ages);
echo (microtime(true) - $start).';';
bucket($ages);
echo (microtime(true) - $start).';';
echo PHP_EOL;
}
Ограниченный тестовый ток
Пожалуйста, проверьте, правильно ли это. Используя php-5.6.15 в командной строке, мои тайминги выглядят примерно так:
elements;loop;sort;filter;bucket
...
4096;0.001507;0.009868;0.01211;0.01453;
8192;0.003704;0.002483;0.02488;0.03035;
16384;0.006660;0.01010;0.05396;0.06723;
32768;0.01417;0.01271;0.09163;0.1163;
...
1048576;0.4227;0.9791;2.983;3.943;
2097152;0.8572;2.320;6.064;8.020;
4194304;1.787;4.981;11.90;16.04;
8388608;3.892;10.84;24.76;33.31;
Для небольшого числа элементов разница между методами не очень велика, но, как вы можете видеть, для наибольшего значения метод loop
в два раза быстрее, чем sort
, в 8 раз быстрее, чем filter
и одиннадцать раз быстрее, чем bucket
. Поэтому, если ваш массив огромен, вы должны использовать loop
.
Ответ 5
Вы можете использовать методы массива next и key.
С помощью next() вы перемещаете указатель массива на одну позицию. С помощью клавиши () вы получите ключ элемента указателя массива. Таким образом, окончательный код будет примерно таким:
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43","Rob"=>"43");
arsort($age);
echo key($age);
next($age);
echo key($age);
Проверьте, работает ли здесь.
Ответ 6
Я бы сделал что-то вроде этого
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43","Rob"=>"43");
$max = max($age); //get the highest age
foreach ($age as $key => $value) { //iterate through $age array
if ($value == $max) { //if the value is equal to max age
echo $key."<br />"; // then echo the key
}
}
Ответ 7
Мне интересно, почему никто не использует встроенное решение:
$age = array("Peter"=>"35","Ben"=>"37","Joe"=>"43","Rob"=>"43");
$new = array_keys($input, max($age));
возвращает массив ("Джо", "Роб")
https://www.php.net/manual/en/function.array-keys.php говорит:
array_keys (массив $ array, смешанный $ search_value [, bool $ strict = FALSE]): массив
Если указано значение search_value, возвращаются только ключи для этого значения. В противном случае все ключи из массива возвращаются.