php中的小排序算法


Small sorting algorithm in php

这应该是一个很简单的算法,但我就是无法绕过它。

我有一些按字母顺序排列的数组

[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写的,所以如果有人能帮助我,我将非常感激。

乌利希期刊指南:代码示例:

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。但别难过,你的帮助不会白费。我可能会给那些帮我解决这个困难算法的人赏金。

再次感谢大家。你的想法启发了我以不同的方式思考

array_chunk()本来是一个解决方案,但由于您希望对其进行特殊排序,因此这对您没有多大帮助。

这是我的五分钱:

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]。

<?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));

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);

查看效果

让我们看看这是否更接近标记

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;
}

Which -当这样运行时:

$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()

end facepalm edit


我会在循环中使用模,当你计算数组索引时(在数组排序之后)-例如,如果你试图将数组分成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
        )
)

可能有一种更整洁的方法(这有点程序化),但它应该能完成工作

如何:

$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
        )
)

为了做到这一点,您需要做两个操作:

首先,将数组尽可能均匀地分成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))按您需要的顺序给出条目。

耶!!我知道了。如果你经常这样做,你可以把它变成一个函数。

# 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"
  }
}

如果简短地说,那么这里是该算法的一个方法。

/**
 * @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测试。