Малый алгоритм сортировки в php - PullRequest
3 голосов
/ 18 октября 2011

Это должен быть довольно простой алгоритм, но я просто не могу обойти его.

У меня есть несколько массивов в алфавитном порядке

[0] => Array
    (
        [0] => a
        [1] => b
        [2] => c
    )

и например

[0] => Array
    (
        [0] => a
        [1] => b
        [2] => c
        [3] => d
    )

и мне нужно отсортировать их по строкам.Например:

Я должен получить таблицу с 3 столбцами и столько строк, сколько она может получить, и она должна быть в алфавитном порядке.

Вот пример: первый массив должен быть преобразован в

[0] => Array
    (
        [0] => Array
            (
                [0] => a
                [1] => b
                [2] => c
            )

    )

Но второй должен быть как

[1] => Array
    (
        [0] => Array
            (
                [0] => a
                [1] => c
                [2] => d
            )
        [1] => Array
            (
                [0] => b
            )
    )

Я пишу это в php, так что если кто-то может помочь, я был бы очень признателен.* UPD: Пример кода:

function sortAsOrdered( array $categories )
{
    foreach ( $categories as $groupId => $group )
    {
        $regroupMenuItems = array();
        $limit            = count( $group );
        $rows             = ceil( $limit / 3 );

        for ( $i = 0; $i < $rows; ++$i )
        {
            $jumper = 0;

            for ( $j = 0; $j < 3; $j++ )
            {
                if ( 0 == $jumper )
                {
                    $jumper = $i;
                }

                if ( isset( $group[ $jumper ] ) )
                {
                    $regroupMenuItems[ $i ][ $j ] = $group[ $jumper ];
                }

                $jumper = $jumper + $rows;
            }
        }

        $categories[ $groupId ] = $regroupMenuItems;
    }

    return $categories;
}

Ребята, я решил это.Здесь вы можете увидеть мой алгоритм http://pastebin.com/xe2yjhYW. Но не расстраивайтесь, ваша помощь не пройдет даром.Я, вероятно, назначу награду только для тех, кто помог мне с этим сложным алгоритмом.

Ребята, еще раз спасибо.Ваши мысли вдохновили меня думать по-другому.

Ответы [ 8 ]

1 голос
/ 18 октября 2011

array_chunk () wold был решением, но если вы хотите, чтобы он был специально отсортирован, это не сильно вам поможет.

Итак, вот мои пять центов:

function array_chunk_vertical($input, $size_max) {
    $chunks = array();
    $chunk_count = ceil(count($input) / $size_max);

    $chunk_index = 0;
    foreach ($input as $key => $value) {
        $chunks[$chunk_index][$key] = $value;

        if (++$chunk_index == $chunk_count) {
            $chunk_index = 0;
        }
    }

    return $chunks;
}


$array = array('a', 'b', 'c', 'd', 'e', 'f');
var_dump(array_chunk_vertical($array, 2));

Что даст вам:

array
  0 => 
    array
      0 => string 'a' (length=1)
      3 => string 'd' (length=1)
  1 => 
    array
      1 => string 'b' (length=1)
      4 => string 'e' (length=1)
  2 => 
    array
      2 => string 'c' (length=1)
      5 => string 'f' (length=1)

Недостатком этой функции является то, что вы можете указать только максимальное количество элементов в чанке, а затем он поровну делит массив на чанки. Так что для [4] и max_size 3 вы получите [2,2] в отличие от ожидаемого [3,1].

0 голосов
/ 25 октября 2011

Если коротко, то вот метод для этого алгоритма.

/**
 * @param array $toTransform
 * @param int $columnsMax
 * @return array
 */
private function transformation( array $toTransform, $columnsMax = 3 )
{
    // First divide array as you need
    $listlen   = count( $toTransform );
    $partlen   = floor( $listlen / $columnsMax );
    $partrem   = $listlen % $columnsMax;
    $partition = array();
    $mark      = 0;

    for ( $px = 0; $px < $columnsMax; $px++ )
    {
        $incr             = ( $px < $partrem ) ? $partlen + 1 : $partlen;
        $partition[ $px ] = array_slice( $toTransform, $mark, $incr );
        $mark             += $incr;
    }

    // Secondly fill empty slots for easy template use
    $result = array();

    for ( $i = 0; $i < count( $partition[0] ); $i++ )
    {
        $tmp = array();

        foreach ( $partition as $column )
        {
            if ( isset( $column[ $i ] ) )
            {
                $tmp[] = $column[ $i ];
            }
            else
            {
                $tmp[] = '';
            }
        }

        $result[] = $tmp;
    }

    return $result;
}

Также для этого я включил тест PHPUnit. Вы можете найти его на этой ссылке .

0 голосов
/ 18 октября 2011

Для этого вам необходимо выполнить две операции:

Сначала разбейте массив на 3 группы как можно более равномерно.

function array_grouped($arr, $group_count)
{
    if (!count($arr)) return array();
    $result = array();
    for ($i = $group_count; $i > 0; --$i)
    {
        # break off the next ceil(remaining count / remaining columns) elements
        # (avoiding FP math, cause that way lies madness)
        $result[] = array_splice($arr, 0, ((count($arr)-1) / $i) + 1);
    }
    return $result;
}

Затем выполните «транспонирование».массив, так что строки и столбцы меняются местами.

function array_transposed($arr)
{
    $result = array();
    foreach ($arr as $x => $subarr)
    {
        foreach ($subarr as $y => $val)
        {
            if (!isset($result[$y])) $result[$y] = array();
            $result[$y][$x] = $val;
        }
    }
    return $result;
}

array_transposed(array_grouped($arr, 3)) дает вам записи в том порядке, в котором вы их хотите.

0 голосов
/ 18 октября 2011

Как насчет:

$arrs = array(
    array('a','b','c'),
    array('a','b','c','d'),
    array('a','b','c','d','e'),
    array('a','b','c','d','e','f'),
    array('a','b','c','d','e','f','g')
);
$nbcols = 3;
foreach ($arrs as $arr) {
    $arr_size = count($arr);
    $nblines = ceil($arr_size/$nbcols);
    $res = array();
    $l = 0;
    foreach ($arr as $el) {
        if ($l == $arr_size - 1 && count($res[0]) < $nbcols) $l=0;
        $res[$l%$nblines][] = $el;
        $l++;
    }
    print_r($res);
}

выход:

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => c
            [2] => d
        )

    [1] => Array
        (
            [0] => b
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => c
            [2] => e
        )

    [1] => Array
        (
            [0] => b
            [1] => d
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => c
            [2] => e
        )

    [1] => Array
        (
            [0] => b
            [1] => d
            [2] => f
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => d
            [2] => g
        )

    [1] => Array
        (
            [0] => b
            [1] => e
        )

    [2] => Array
        (
            [0] => c
            [1] => f
        )

)
0 голосов
/ 18 октября 2011

YAYAYAY !! Я понял. Вы можете превратить это в функцию, если будете делать это регулярно.

# Here we setup our array and the number of columns we want.
$myArray = range('a','d');  
$numCols = 3;

# Here we break ourselves up into columns
for ($i = 0; $i < $numCols; $i++) {
    $numRows = ceil(count($myArray) / ($numCols - $i));
    $columns[$i] = array_slice($myArray,0,$numRows);
    $myArray = array_slice($myArray,$numRows);
}

# Here we transpose our array to be in rows instead of columns.
for ($i = 0; $i < $numCols; $i++) {
    for ($j = 0; $j < count($columns[$i]); $j++) {
        $rows[$j][$i] = $columns[$i][$j];
    }
}

# Our rows are now in $rows
var_dump($rows);

Выходные данные:

array(2) {
  [0]=>
  array(3) {
    [0]=>
    string(1) "a"
    [1]=>
    string(1) "c"
    [2]=>
    string(1) "d"
  }
  [1]=>
  array(1) {
    [0]=>
    string(1) "b"
  }
}
0 голосов
/ 18 октября 2011

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

$input = range('a', 'k');  // arbitrary
$columns = 3;  // configure this
$rows = ceil(count($input) / $columns);

// fugly, but this way it works without declaring a function
// and also in PHP < 5.3 (on 5.3 you'd use a lambda instead)
$order = create_function('$i',
                         '$row = (int)($i / '.$rows.');'.
                         '$col = $i % '.$rows.';'.
                         'return $col * ('.$columns.' + 1) + $row;');

// $order is designed to get the index of an item in the original array,
// and produce the index that item would have if the items appeared in
// column-major order instead of row-major as they appear now
$array = array_map($order, array_keys($input));

// replace the old keys with the new ones
$array = array_combine($array, $input);

// sort based on the new keys; this will effectively transpose the matrix,
// if it were already structured as a matrix instead of a single-dimensional array
ksort($array);

// done!
$array = array_chunk($array, $columns);
print_r($array);

См. Его в действии .

0 голосов
/ 18 октября 2011
<?php

$five_el = array('a', 'b', 'c', 'd', 'e');

$two_el = array('a', 'b');

$three_el = array('a', 'b', 'c');

$six_el = array('a', 'b', 'c', 'd', 'e', 'f');

function multid($sorted_array) {
    $mulidarray = array();
    $row = 0;
    $column = 0;
    foreach ($sorted_array as $value) {
        if ($column == 3) {
            $row++;
        }
        $column++;
        if (!isset($mulidarray[$row])) {
            $mulidarray[$row] = array();
        }
        $multidarray[$row][] = $value;
    }

    return $multidarray;
}

var_dump(multid($five_el));
var_dump(multid($two_el));
var_dump(multid($three_el));
var_dump(multid($six_el));
0 голосов
/ 18 октября 2011

Давайте посмотрим, ближе ли это к отметке

function splitVerticalArrayIntoColumns($aInput, $iNumberOfColumns) {

  //output array
  $aOutput = array();

  //the total length of the input array
  $iInputLength = count($aInput);

  //the number of rows will be ceil($iInputLength / $iNumberOfColumns)
  $iNumRows = ceil($iInputLength / $iNumberOfColumns);

  for($iInputIndex = 0; $iInputIndex < $iInputLength; $iInputIndex++) {
    $iCurrentRow = $iInputIndex % $iNumRows;
    $aOutput[$iCurrentRow][] = $aInput[$iInputIndex];
  }

  //return
  return $aOutput;
}

Который - при выполнении таким образом:

$aList = array("a", "e", "d", "b", "c");
echo 'array("a", "e", "d", "b", "c")' . "\n\n";
print_r(splitVerticalArrayIntoColumns($aList, 3));

Дает:

array("a", "e", "d", "b", "c")

Array
(
    [0] => Array
        (
            [0] => a
            [1] => d
            [2] => c
        )

    [1] => Array
        (
            [0] => e
            [1] => b
        )

)

Это еще не сортировка каждой строки, но разве это то, что вам нужно?



начать редактирование лицевой стороны

...или, конечно, array_chunk($aList, 3) после того, как вы отсортировали его O_o

http://uk3.php.net/manual/en/function.array-chunk.php

Я оставлю все ниже для справки или чего-то еще - я полностью забыл о array_chunk ()

редактирование конечной лицевой стороны


Я бы использовал модуль в цикле, где вы подсчитываете индекс массива (после сортировки массива) - например, есливы пытаетесь разделить массив на 3 "столбца", вы можете попробовать что-то вроде:

if($iIndex % 3 == 0) {
  //... create a new array
}
else {
  //... add to an existing array
}

РЕДАКТИРОВАТЬ пример кода:

$aList = array("a", "e", "d", "b", "c");
sort($aList);

$iDesiredNumberOfColumns = 3;
$iListLength = count($aList);

$aListInColumns = array();
$iRowNumber = 0;

for($iIndex = 0; $iIndex < $iListLength; $iIndex++) {
  $iColumnNumber = $iIndex % 3;
  if($iIndex != 0 && $iColumnNumber == 0) {
    $iRowNumber++;
  }

  $aListInColumns[$iRowNumber][$iColumnNumber] = $aList[$iIndex];
}

Просто запустил его на моем локальном сервере (иисправил опечатку), и он выдает следующее:

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )

    [1] => Array
        (
            [0] => d
            [1] => e
        )

)

Возможно, есть более аккуратный способ сделать это (это немного процедурно), но он должен делать свою работу.

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