PHP无法为任意长度的二维数组编写重新排序函数

时间:2013-08-02 22:41:30

标签: php arrays sorting recursion

从广义上讲,我有一个以下格式的二维数组:

$elements = array(  0 => array('typeA', 'desc'),
                    1 => array('typeB', 'desc'),
                    2 => array('typeA', 'desc'),
                    n => array('typeC', 'desc'));

typeX可以是5种可能中的1种,而desc可以是任何可能性。最终目标是$elements排序,以便共享typeX的两个元素不会相邻。这是我的功能:

function fixDbls($elems) {
    $final   = array();
    $singles = array();
    $doubles = array();
    $lastelem = null;
    foreach($elems as $elem) {
        if(!$lastelem) { // set this the first time through
            $lastelem = $elem[0];
            $singles[] = $elem;
        } else { //otherwise, sort!
            if($lastelem == $elem[0]) {
                $doubles[] = $elem;
            } else {
                $singles[] = $elem;
            }
        }
    }

    if ($doubles) {
            // I suspect this is where it all goes wrong, I am awful at recursion!
        $final = fixDbls(array_merge($singles, $doubles));
    } else {
        $final = $singles;
    }

    return $final;
}

如果有人能帮助我理解为什么这不起作用(不仅仅是代码,但是,我做了一个错误的假设,或者我对这个问题的思考背叛了我 - 帮助使这对公众更有用) !)我会永远,非常感激。

2 个答案:

答案 0 :(得分:1)

我一直在想你的问题,我想我想出了一个解决方案。

code:

<?php

function print_array( $s, $a )
{
    echo $s.': { ';
    foreach ( $a as $k => $aa ) {
        echo $k.' => ';
        if ( is_array($aa) ) {
            echo '{ '.implode( ', ', $aa ).' }, ';
        } else {
            echo $aa.', ';
        }
    }
    echo '}'.PHP_EOL;
}

function search_array( array $a, $k )
{
    $found = false;
    foreach ( $a as $kk => $aa ) {
        if ( $aa[0] == $k ) {
            $found = $kk;
            break;
        }
    }

    return $found;
}

$input = array(  
        array('typeA', 'desc'),
            array('typeB', 'desc'),
                array('typeA', 'desc'),
                array('typeC', 'desc')
);

print_array( 'Initial input', $input );
$frequencies = array();

foreach ( $input as $e ) {
    $frequencies[ $e[0] ] = array_key_exists( $e[0], $frequencies ) ? $frequencies[ $e[0] ] + 1 : 1;
}

arsort($frequencies);

print_array( 'Frequencies', $frequencies );
$tail = array_slice( $frequencies, 1 );
$maxFreq = current( $frequencies ); 
$orderedElems = array_keys( $frequencies );
$mostFreq = current( $orderedElems );

echo 'The most frecuent element is "'.$mostFreq.'"'.PHP_EOL;

if ( array_sum( $tail ) < $maxFreq - 1 ) {
    die ('There\'s No possible solution'.PHP_EOL);
}

$ouput = array();

for ( $i = 0; $i < $maxFreq; $i++ ) {
    $k = search_array( $input, $mostFreq);
    $output[] = $input[ $k ];
    unset( $input[ $k ] );
}

print_array( 'Input after removing "'.$mostFreq.'"', $input );

echo '-----'.PHP_EOL;
print_array( 'Before process, output', $output );

foreach ( $tail as $e => $f ) {
    $i = 1;
    echo 'Elem to place: "'.$e.'" ('.$f.' times)'.PHP_EOL;
    while ( ( $k = search_array( $input, $e ) ) !== false ) {
        echo '$i: '.$i.PHP_EOL;
        $begin = array_slice( $output, 0, $i );
        print_array( 'Begin', $begin );
        $end = array_slice( $output, $i );
        print_array( 'End', $end );
        $output = array_merge( $begin, array( $input[$k] ), $end );
        print_array( 'Output', $output );
        $i+=2;
        unset( $input[$k] );
        echo PHP_EOL;
    }
}

print_array( 'Final output', $output );

这一次,我只是尝试了你提出问题的例子。最终结果是:

Final output: { 0 => { typeA, desc }, 1 => { typeB, desc }, 2 => { typeC, desc }, 3 => { typeA, desc }, }

我希望这个版本符合您的需求。

答案 1 :(得分:0)

我现在已经成功了。这应该是最好的。

$elements = array(0 => array('typeA', 'desc'), 1 => array('typeA', 'desc'), 2 => array('typeB', 'desc'), 3 => array('typeC', 'desc'), 4 => array('typeC', 'desc'), 5 => array('typeB', 'desc'), 6 => array('typeB', 'desc'), 7 => array('typeD', 'desc'), 8 => array('typeD', 'desc'), 9 => array('typeA', 'desc'), 10 => array('typeA', 'desc'));
function sortDeep($ary){
  foreach($ary as $a){
    foreach($a as $i => $v){
      if($i === 0)$typesArray[] = $v;
    }
  }
  function notNextTo($a, $b){
    if($a === $b){
      return 1;
    }
    else{
      return 0;
    }
  }
  uasort($typesArray, 'notNextTo'); $ak = array_keys($typesArray);
  foreach($ary as $i => $v){
    $sorted[$i] = $ary[$ak[$i]];
  }
  return $sorted;
}
print_r(sortDeep($elements));