从广义上讲,我有一个以下格式的二维数组:
$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;
}
如果有人能帮助我理解为什么这不起作用(不仅仅是代码,但是,我做了一个错误的假设,或者我对这个问题的思考背叛了我 - 帮助使这对公众更有用) !)我会永远,非常感激。
答案 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));