Как отсортировать массив PHP численно в последовательном порядке - PullRequest
0 голосов
/ 30 июня 2018

Спасибо за внимание,

У меня есть массив PHP $array = array(1,1,1,2,3,2,3,4,5,4,4,4,5,1,2,2,3);, и я пытаюсь отсортировать его в повторяющемся последовательном порядке числового порядка с самыми большими наборами вначале.

В приведенном выше массиве у меня самое высокое значение 5, которое появляется дважды, поэтому первые два набора будут 1,2,3,4,5, затем оно вернется ко второму, наибольшему набору значений и т. Д.

Я хотел бы закончить с 1,2,3,4,5,1,2,3,4,5,1,2,3,4,1,2,4.

Будем весьма благодарны за любые указатели в правильном направлении.

Обновление: я почти уверен, что могу разбить массив на куски целочисленных значений, затем последовательно выбрать элемент из каждого подмассива, пока не останется ни одного элемента, но я просто чувствую, что это будет плохо для производительности, и я не не хочу пропустить простой трюк, с которым PHP уже может справиться.

Ответы [ 4 ]

0 голосов
/ 30 июня 2018
<?php

$array = array(1,1,1,2,3,2,3,4,5,4,4,4,5,1,2,2,3);
sort($array);

while($array) {
    $n = 0;
    foreach($array as $k => $v) {
        if($v>$n) {
            $result[] = $n = $v;
            unset($array[$k]);
        }
    }
}

echo implode(',', $result);

Выход:

1,2,3,4,5,1,2,3,4,5,1,2,3,4,1,2,4
0 голосов
/ 30 июня 2018

Вы можете использовать только линейную логику для сортировки с использованием функций php. Вот оптимизированный способ заполнения структур данных. Его можно использовать для потоков, генераторов или чего-либо еще, что вы можете повторять и сравнивать.

$array = array(1,1,1,2,3,2,3,4,5,4,4,4,5,1,2,2,3);
sort($array);
$chunks = [];
$index = [];
foreach($array as $i){
    if(!isset($index[$i])){
        $index[$i]=0;
    }
    if(!isset($chunks[$index[$i]])){
        $chunks[$index[$i]]=[$i];
    } else {
        $chunks[$index[$i]][] = $i;
    }
    $index[$i]++;
}
$result = call_user_func_array('array_merge', $chunks);
print_r($result);
0 голосов
/ 30 июня 2018

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

Поскольку нет разницы между одним 1 и другим, все, что вам действительно нужно, это подсчитать, сколько раз каждый из них появляется. Оказывается, PHP может сделать это для вас с aaray_count_values ​​.

$sets = array_count_values ($input);

Затем мы можем убедиться, что наборы в порядке, отсортировав по ключу:

ksort($sets);

Теперь мы перебираем наши множества, считая, сколько раз мы вывели каждое число. Как только мы «опустошим» набор, мы удалим его из списка, и когда у нас не останется наборов, мы все сделали:

$output = [];
while ( count($sets) > 0 ) {
    foreach ( $sets as $number => $count ) {
        $output[] = $number;
        if ( --$sets[$number] == 0 ) {
            unset($sets[$number]);
        }
     }
 }

Этот алгоритм может быть адаптирован для случаев, когда значения фактически различны, но могут быть помещены в наборы, так как значение каждого набора должно быть списком, а не счетчиком. Вместо - вы бы использовали array_shift, а затем проверили, равна ли длина набора нулю.

0 голосов
/ 30 июня 2018

Вот моя попытка очень ручного цикла с использованием процесса, идея в том, чтобы просто отсортировать числа в контейнеры для array_unshifting. Я уверен, что это ужасно, и я хотел бы, чтобы кто-то сделал это в пять строк или меньше:)

$array = array(1,1,1,2,3,2,3,4,5,4,4,4,5,1,2,2,3);
sort($array);
// Build the container array
$numbers = array_fill_keys(array_unique($array),array());
// Assignment
foreach( $array as $number )
{
  $numbers[ $number ][] = $number;
}

// Worker Loop
$output = array();
while( empty( $numbers ) === false )
{
  foreach( $numbers as $outer => $inner )
  {
    $output[] = array_shift( $numbers[ $outer ] );
    if( empty( $numbers[ $outer ] ) )
    {
      unset( $numbers[ $outer ] );
    }
  }
}

var_dump( $output );
...