0

大まかに言えば、次の形式の 2 次元配列があります。

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

どこtypeXで 5 つの可能性のうちの 1 つであり、desc何でもかまいません。最終目標は$elements、a を共有する 2 つの要素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;
}

これがうまくいかない理由を誰かが理解するのを手伝ってくれたら (コードだけでなく、私が間違った仮定をした場所や、この問題についての私の考えが私を裏切った場所など)、これを一般の人々にとってより一般的に役立つものにするのに役立ちます!)これまでになく、とても感謝しています。

4

2 に答える 2

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

このバージョンがあなたのニーズに合っていることを願っています。

于 2013-08-04T23:36:11.157 に答える