Знайдіть найвищу цінність у багатовимірному масиві

Проблема

У мене є багатовимірний масив, подібний до наведеного нижче. Те, що я намагаюся досягти, - це спосіб знайти та витягнути з масиву той, який має найвище значення "Загальна", тепер я знаю, що є функція max , але це не працює з багатовимірний масив, як це.

Що я думав про те, що створює foreach-цикл і створює новий масив із загальними значеннями, а потім, використовуючи max , щоб знайти максимальне значення, яке буде працювати, тоді одне питання буде вилучено решта даних, що стосуються цього максимального значення. Я не впевнений, що це найефективніший спосіб.

Будь-які ідеї?

Array
(
    [0] => Array
        (
            [Key1] => Key1
            [Total] => 13
        )

    [1] => Array
        (
            [Key2] => Key2
            [Total] => 117
        )

    [2] => Array
        (
            [Key3] => Key3
            [Total] => 39
        )
)
19
Якщо вам не потрібна така продуктивність - буде добре два петлі. Якщо ви хочете отримати величезне збільшення продуктивності в масивах, маючи дуже багато елементів, вам слід використовувати інтервальні дерева (дерева сегментів) для зберігання значень. Але це величезна теорія і може бути не потрібна у вашому випадку.
додано Автор Kamen Stoykov, джерело

8 Відповіді

Оскільки PHP 5.5 ви можете використовувати array_column , щоб отримати масив значень для певної ключові, а макс його.

max (array_column ($ array, 'Total'))

28
додано
Це працює для мене :)
додано Автор Jonjie, джерело

Just do a simple loop and compare values or use array_reduce

$data = array_reduce($data, function ($a, $b) {
    return @$a['Total'] > $b['Total'] ? $a : $b ;
});

print_r($data);

Дивіться демонстраційну версію

19
додано
Хоча, використовуючи @ , а не перевіряти наявність дійсного значення, це погана практика, це, насправді, найбільш правильна відповідь. array_reduce призначений для подібного роду рішень.
додано Автор halfpastfour.am, джерело

Це настільки базовий алгоритм.

$max = -9999999; //will hold max val
$found_item = null; //will hold item with max val;

foreach($arr as $k=>$v)
{
    if($v['Total']>$max)
    {
       $max = $v['Total'];
       $found_item = $v;
    }
}

echo "max value is $max";
print_r($found_item);

Робоча демонстрація

13
додано
Замість -9999 ініціалізувати з першим значенням (у цьому прикладі буде $ array [0] ["Total"] ) або спеціальне значення, наприклад NULL або false (тоді вам доведеться перевірити NULL/false в статті if ).
додано Автор Salman A, джерело
Ви можете ініціювати його за допомогою "$ max = ~ PHP_INT_MAX;" Перевірте основи пошуку мінімальної кількості. Інший варіант полягає в тому, щоб ініціювати його першим елементом масиву
додано Автор Robert, джерело
тому що вам потрібно мати мінімальне значення для порівняння з першим часом, і ви повинні бути впевнені, що це значення менше, ніж перший елемент. Це може бути зроблено також з assiging перший елемент масиву, але тоді мені потрібно буде почати цикл з другого елемента в масиві.
додано Автор Robert, джерело
змінити $ v ['Total']> $ max на $ v ['Total'] <$ max і поставити $ max = 9999999999; ви можете змінювати імена змін для деяких видимості $ max до $ min
додано Автор Robert, джерело
Або можна використовувати -Inf :)
додано Автор Terry, джерело
Ви можете завжди просто ініціалізувати його як $ max = null; , просто додайте ще одне умова, щоб перевірити, що вже встановлено $ max , наприклад if ($ v ['Total']> $ max ||! $ Max) . У цьому випадку, коли вперше він проходить через цикл, і значення не визначено $ max , він буде встановлювати його. Припущення полягає в тому, що, навіть якщо це єдине значення, воно технічно буде максимумом, незалежно від того, який довільний мінімальний тий буде закодований.
додано Автор Mike, джерело
Чому ви ініціалізуєте $ max з -9999999 ?
додано Автор halfpastfour.am, джерело
Ні, моє запитання було чому?
додано Автор halfpastfour.am, джерело
просто протилежне цьому для мін значення ???
додано Автор Bugfixer, джерело

Я знаю, що це питання старе, але я даю наступну відповідь у відповідь на інше питання, яке вказано тут після того, як було позначено як дублікат. Це ще одна альтернатива, яку я не бачу в поточних відповідях.

Я знаю, що є функція з назвою max, але це не працює з багатовимірним масивом, як це.

Ви можете обійти це з допомогою array_column , що робить максимальну цінність дуже простим:

$arr = [['message_id' => 1,
             'points' => 3],
        ['message_id' => 2,
             'points' => 2],
        ['message_id' => 3,
             'points' => 2]];

// max value
$max = max(array_column($arr, 'points'));

Отримання асоціативного ключа є де він стає трохи складніше, враховуючи, що ви дійсно можете хочете, щоб декілька ключів (якщо $ max відповідає більш ніж одному значенню). Ви можете зробити це за допомогою анонімної функції в array_map і скористайтеся функцією array_filter , щоб видалити значення null :

// keys of max value
$keys = array_filter(array_map(function ($arr) use ($max) {
    return $arr['points'] == $max ? $arr['message_id'] : null;
}, $arr));

Вихід:

array(1) {
  [0]=>
  int(1)
}

Якщо ви в кінцевому підсумку з кількома клавішами, але зацікавлені лише в знайденому першому збігу, просто посилайтеся на $ keys [0] .

5
додано

інший простий спосіб буде

$max  = array_map( function( $arr ) {
  global $last;
  return (int)( ( $arr["Total"] > $last ) ? $arr["Total"] : $last );
}, $array );

print_r( max( $max ) );
2
додано
<?php
$myarray = array(
    0 => array(
        'Key1' => 'Key1',
        'Total' => 13,
    ),
    1 => array(
        'Key2' => 'Key2',
        'Total' => 117,
    ),
    2 => array(
        'Key2' => 'Key3',
        'Total' => 39,
    ),
);

$out = array();
foreach ($myarray as $item) {
    $out[] = $item['Total'];
}

echo max($out); //117

unset($out, $item);
1
додано

You can use PHP usort function: http://php.net/manual/en/function.usort.php

Тут подано гарний ілюстративний приклад:

<?php
function cmp($a, $b)
{
 return strcmp($a["fruit"], $b["fruit"]);
}

$fruits[0]["fruit"] = "lemons";
$fruits[1]["fruit"] = "apples";
$fruits[2]["fruit"] = "grapes";

usort($fruits, "cmp");

while (list($key, $value) = each($fruits)) {
 echo "\$fruits[$key]: " . $value["fruit"] . "\n";
}

?>

Таким чином, буде сортувати максимальне значення до останнього індексу масиву.

Вихід:

$fruits[0]: apples
$fruits[1]: grapes
$fruits[2]: lemons

Цей приклад наведено на згаданому вище посилання

1
додано
Я б не рекомендував використовувати алгоритм складного сортування, щоб отримати щось подібне для одержання єдиного значення з масиву. Насправді, сортування потрібно робити лише тоді, коли це дійсно потрібно. Додаткові накладні витрати не є цінними для "прохолодного" рішення.
додано Автор Marcello Mönkemeyer, джерело
Фактична сортування, оскільки воно вимагає декількох переходів та порівнянь, а також багаторазових переміщень та перестановки ключів масиву. Залежно від реалізованого алгоритму сортування (на жаль, я не знаю, який з них використовує PHP), це може зростати експоненціально. Це може не мати ніякої помітної різниці для малих масивів, і коли він використовується кілька разів, але уявіть, що він постійно використовується в рамках, як Symfony або Laravel - це буде величезним bummer.
додано Автор Marcello Mönkemeyer, джерело
@ MarcelloMönkemeyer, що саме та додаткова накладна ціна, про яку ви тут посилаєтеся? Для отримання єдиного значення (макс або мінімум) весь масив потрібно пройти (шляхом порівняння). Функція вище теж робить те ж саме, якщо мені не вистачає чогось тут!
додано Автор Umair Khan, джерело

Можна виконати за допомогою array_walk (array_walk_recursive, якщо потрібно)

$ arr - це масив, в якому ви хочете здійснити пошук

$largestElement = null;

array_walk($arr, function(&$item, $key) use (&$largestElement) {
    if (!is_array($largestElement) || $largestElement["Total"] < $item["Total"]) {
        $largestElement = $item;
    }
});
1
додано
Ukrainian PHP comunity
Ukrainian PHP comunity
885 учасників

dev-ua/php