Пользовательская сортировка многомерных с n элементов по наибольшему значению - PullRequest
9 голосов
/ 17 апреля 2019

В настоящее время я могу сортировать многомерный массив с помощью пользовательского метода сортировки. Каждый массив lineupSet имеет количество элементов n. Функция sort_points будет сортировать каждую lineupSet от самой высокой до самой низкой totalPoints, а затем даст мне lineupSet с наибольшим общим значением totalPoints. В настоящее время я меняю подход, я все еще хочу отсортировать сначала каждый lineupSet и упорядочить по возрастанию к наименьшему Тогда я хотел бы получить наибольшее значение totalPoints каждого lineupSet на основе данного количества. Каков наилучший способ приблизиться к этому?

Тестовый массив:

$testArray = [[
    "lineupSet" => [
        [[
            "formula" => [
                "totalPoints" => 214.61,
            ],
            "name"    => "arr0-test0",
        ], [
            "formula" => [
                "totalPoints" => 201.17,
            ],
            "name"    => "arr0-test1",
        ]], [
            "formula" => [
                "totalPoints" => 5.01,
            ],
            "name"    => "arr0-test2",
        ]],
], [
    "lineupSet" => [
        [[
            "formula" => [
                "totalPoints" => 214.76,
            ],
            "name"    => "arr1-test0",
        ], [
            "formula" => [
                "totalPoints" => 220.66,
            ],
            "name"    => "arr1-test1",
        ]],
    ],
], [
    "lineupSet" => [
        [[
            "formula" => [
                "totalPoints" => 205.71,
            ],
            "name"    => "arr2-test0",
        ], [
            "formula" => [
                "totalPoints" => 204.43,
            ],
            "name"    => "arr2-test1",
        ]],
    ],
], [
    "lineupSet" => [
        [[
            "formula" => [
                "totalPoints" => 205.48,
            ],
            "name"    => "arr3-test0",
        ], [
            "formula" => [
                "totalPoints" => 203.51,
            ],
            "name"    => "arr3-test1",
        ]],
    ],
]];

Функция сортировки

function sum_points($v) {
    $totalPoints = 0;
    foreach ($v['lineupSet'] as $lset) {
        if (isset($lset['formula'])) {
            $totalPoints += $lset['formula']['totalPoints'];
        }
        else {
            foreach ($lset as $l) {
                $totalPoints += $l['formula']['totalPoints'];
            }
        }
    }
    return $totalPoints;
}

function sort_points($a, $b) {
    return sum_points($b) - sum_points($a);
}

usort($testArray, 'sort_points');
print_r($testArray[0]);

Например, я хочу получить два верхних «максимальных балла». Желаемый результат:

Array (
    [lineupSet] => Array
        (
            [0] => Array
                (
                    [0] => Array
                        (
                            [formula] => Array
                                (
                                    [totalPoints] => 220.66
                                )

                            [name] => arr1-test1
                        )

                    [1] => Array
                        (
                            [formula] => Array
                                (
                                    [totalPoints] => 214.76
                                )

                            [name] => arr0-test0
                        )

                )

        )

)

Я хочу сделать то же самое для верха n наивысшего totalPoints. Помня о том, что иногда придется брать n предметов из каждого lineupSet, которые являются самыми высокими totalPoints.

Ответы [ 4 ]

5 голосов
/ 22 апреля 2019

Я думаю, что лучше использовать объект, тогда вы можете сохранить максимальное значение при сортировке данных (также вы можете использовать конструктор для сортировки массива).

Class SortHelper{
    public $max = 0;

    private function checkMax($totalPoints){
        if($totalPoints > $this->max)
            $this->max = $totalPoints;
    }

    private function sum_points($v) {
        $totalPoints = 0;
        foreach ($v['lineupSet'] as $lset) {
            if (isset($lset['formula'])) {
                $totalPoints += $lset['formula']['totalPoints'];
                $this->checkMax($lset['formula']['totalPoints']);
            }
            else {
                foreach ($lset as $l) {
                    $totalPoints += $l['formula']['totalPoints'];
                    $this->checkMax($l['formula']['totalPoints']);
                }
            }
        }
        return $totalPoints;
    }

    private function sort_points($a, $b) {
        return $this->sum_points($b) - $this->sum_points($a);
    }

    public function sort($array){
        usort( $array, [$this, 'sort_points']); 
        return $array;
    }
}

тогда у вас будет:

$sortHelper = new SortHelper();
$sorted_array = $sortHelper->sort($testArray);

var_dump($sorted_array[0]);
var_dump($sortHelper->max);
1 голос
/ 23 апреля 2019

Пожалуйста, попробуйте эти 2 функции, выполнив следующие шаги:

  1. sort_points(); Сортируйте его с помощью функции PHP arsort и верните в новый упрощенный массив.
  2. transform_arrays($sortedArray, $testArray); $ testArray изменит значение с помощью sortedArray.
  3. скопируйте все коды в один файл .php и запустите его.

* я предполагаю, что нас не волнует сложность, и в реальной жизни (в данном случае в моей жизни) нет ничего такого, что нужно сортировать в многомерном массиве, потому что массивэто просто хранилище для хранения данных, которые могут быть прочитаны человеком.


<code><?php

$testArray = 
    [
        ['lineupSet' => [[['formula' => ['totalPoints' => 214.61],'name' => 'arr0-test0'],['formula' => ['totalPoints' => 220.66],'name' => 'arr1-test1']]]],
        ['lineupSet' => [[['formula' => ['totalPoints' => 205.71],'name' => 'arr2-test0'],['formula' => ['totalPoints' => 204.43],'name' => 'arr2-test1']]]],
        ['lineupSet' => [[['formula' => ['totalPoints' => 205.48],'name' => 'arr3-test0'],['formula' => ['totalPoints' => 203.51],'name' => 'arr3-test1']]]]
    ];

// sort into another array
function sort_points($testArray = []){
    $response = $result = [];
    $i = 0;
    foreach($testArray as $array2){
        foreach($array2['lineupSet'][0] as $item){
           $result[$item['name']] = $item['formula']['totalPoints'];
           $i++;
        }
    }
    arsort($result);

    $i = 0;
    foreach($result as $key => $val){
        $response[$i]['name'] = $key;
        $response[$i]['totalPoints'] = $val;
        $i++;
    }
    return $response;
}

// this won't work if the $testArray format structure is changed
function transform_arrays($items, $testArray){

    $l = 0;
    for($i=0;$i<count($testArray);$i++){
        for($j=0;$j<count($testArray[$i]);$j++){
            for($k=0;$k<count($testArray[$i]['lineupSet'][$j]);$k++){
                $testArray[$i]['lineupSet'][$j][$k]['formula']['totalPoints'] = $items[$l]['totalPoints'];
                $testArray[$i]['lineupSet'][$j][$k]['name'] = $items[$l]['name'];
                // print_r($testArray[$i]['lineupSet'][$j][$k]['formula']['totalPoints']);
                // print_r($testArray[$i]['lineupSet'][$j][$k]);
                $l++;
            }

        }
    }
    return $testArray;
}

echo '<pre>';
$sortedArray = sort_points($testArray);
$response = transform_arrays($sortedArray, $testArray);
print_r($response);
echo '
';
0 голосов
/ 26 апреля 2019

Похоже, вы хотите найти топ-2 записей, отсортированных по убыванию точек. Вы можете просто перебрать все записи, содержащие ключ formula и добавить их в массив, а затем отсортировать их:

$pointsArray = array();
foreach ($testArray as $array1) {
    foreach ($array1["lineupSet"] as $array2) {
        if (isset($array2["formula"])) {
            $pointsArray[] = $array2;
        } else {
            foreach ($array2 as $array3) {
                $pointsArray[] = $array3;
            }
        }
    }
}
usort($pointsArray, function($item1, $item2) {
    $points1 = $item1["formula"]["totalPoints"];
    $points2 = $item2["formula"]["totalPoints"];
    return $points1 > $points2 ? -1 : ($points1 < $points2 ? 1 : 0);
});
$pointsArray = array_slice($pointsArray, 0, 2); // top 2 items
var_dump($pointsArray); // or array(array("lineupSet" => $pointsArray))

Выход:

array(2) {
  [0]=>
  array(2) {
    ["formula"]=>
    array(1) {
      ["totalPoints"]=>
      float(220.66)
    }
    ["name"]=>
    string(10) "arr1-test1"
  }
  [1]=>
  array(2) {
    ["formula"]=>
    array(1) {
      ["totalPoints"]=>
      float(214.76)
    }
    ["name"]=>
    string(10) "arr1-test0"
  }
}
0 голосов
/ 26 апреля 2019

Проверьте это,

$n = 2; // number of elements 

$testArray = [[
    "lineupSet" => [
        [[
            "formula" => [
                "totalPoints" => 214.61,
            ],
            "name"    => "arr0-test0",
        ], [
            "formula" => [
                "totalPoints" => 201.17,
            ],
            "name"    => "arr0-test1",
        ]], [
            "formula" => [
                "totalPoints" => 5.01,
            ],
            "name"    => "arr0-test2",
        ]
    ],
], [
    "lineupSet" => [
        [[
            "formula" => [
                "totalPoints" => 214.76,
            ],
            "name"    => "arr1-test0",
        ], [
            "formula" => [
                "totalPoints" => 220.66,
            ],
            "name"    => "arr1-test1",
        ]],
    ],
], [
    "lineupSet" => [
        [[
            "formula" => [
                "totalPoints" => 205.71,
            ],
            "name"    => "arr2-test0",
        ], [
            "formula" => [
                "totalPoints" => 204.43,
            ],
            "name"    => "arr2-test1",
        ]],
    ],
], [
    "lineupSet" => [
        [[
            "formula" => [
                "totalPoints" => 205.48,
            ],
            "name"    => "arr3-test0",
        ], [
            "formula" => [
                "totalPoints" => 203.51,
            ],
            "name"    => "arr3-test1",
        ]],
    ],
]];

function sort_points($a, $b)
{
    return ($a['formula']['totalPoints'] > $b['formula']['totalPoints']) ? -1 : 1;
}

$result = [];

$reference = &$result['lineupSet'][0]; // store reference in $reference

foreach ($testArray as $tA) {
    foreach ($tA['lineupSet'] as $t) {
        foreach ($t as $child) {
            $reference[] = $child;
        }
    }
}

usort($reference, 'sort_points');
$reference = array_slice($reference, 0, $n);
var_dump($result); // desired output
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...