0

我有以下两个数组:

<?php
  $a = array( // actions
    'left' => 'LEFT',
    'middle' => 'MIDDLE',
    'right' => 'RIGHT',
  );
  $m = array( // modifiers
    'ctrl' => 'CTRL',
    'alt' => 'ALT',
    'shift' => 'SHIFT',
    'double' => 'DOUBLE',
  );
?>

我需要得到笛卡尔积,但需要注意的是也需要组合的每种组合。当然,如果我向数组添加更多选项,它需要扩展。所以生成的列表应该输出如下:

<?php
$options['left'] = 'LEFT';
$options['LEFT'] = array(
  'ctrl_left' => 'CTRL+LEFT',
  'alt_left' => 'ALT+LEFT',
  'shift_left' => 'SHIFT+LEFT',
  'double_left' => 'DOUBLE+LEFT',
  'ctrl_alt_left' => 'CTRL+ALT+LEFT',
  'ctrl_shift_left' => 'CTRL+SHIFT+LEFT',
  'ctrl_double_left' => 'CTRL+DOUBLE+LEFT',
  'alt_shift_left' => 'ALT+SHIFT+LEFT',
  'alt_double_left' => 'ALT+DOUBLE+LEFT',
  'ctrl_alt_shift_left' => 'CTRL+ALT+SHIFT+LEFT',
  'ctrl_alt_double_left' => 'CTRL+ALT+DOUBLE+LEFT',
  'ctrl_alt_shift_double_left' => 'CTRL+ALT+SHIFT+DOUBLE+LEFT',
);
$options['middle'] = 'MIDDLE';
$options['MIDDLE'] = array(
  'ctrl_middle' => 'CTRL+MIDDLE',
  'alt_middle' => 'ALT+MIDDLE',
  'shift_middle' => 'SHIFT+MIDDLE',
  'double_middle' => 'DOUBLE+MIDDLE',
  'ctrl_alt_middle' => 'CTRL+ALT+MIDDLE',
  'ctrl_shift_middle' => 'CTRL+SHIFT+MIDDLE',
  'ctrl_double_middle' => 'CTRL+DOUBLE+MIDDLE',
  'alt_shift_middle' => 'ALT+SHIFT+MIDDLE',
  'alt_double_middle' => 'ALT+DOUBLE+MIDDLE',
  'ctrl_alt_shift_middle' => 'CTRL+ALT+SHIFT+MIDDLE',
  'ctrl_alt_double_middle' => 'CTRL+ALT+DOUBLE+MIDDLE',
  'ctrl_alt_shift_double_middle' => 'CTRL+ALT+SHIFT+DOUBLE+MIDDLE',
);

$options['right'] = 'RIGHT';
$options['RIGHT'] = array(
  'ctrl_right' => 'CTRL+RIGHT',
  'alt_right' => 'ALT+RIGHT',
  'shift_right' => 'SHIFT+RIGHT',
  'double_right' => 'DOUBLE+RIGHT',
  'ctrl_alt_right' => 'CTRL+ALT+RIGHT',
  'ctrl_shift_right' => 'CTRL+SHIFT+RIGHT',
  'ctrl_double_right' => 'CTRL+DOUBLE+RIGHT',
  'alt_shift_right' => 'ALT+SHIFT+RIGHT',
  'alt_double_right' => 'ALT+DOUBLE+RIGHT',
  'ctrl_alt_shift_right' => 'CTRL+ALT+SHIFT+RIGHT',
  'ctrl_alt_double_right' => 'CTRL+ALT+DOUBLE+RIGHT',
  'ctrl_alt_shift_double_right' => 'CTRL+ALT+SHIFT+DOUBLE+RIGHT',
);
?>
4

3 回答 3

1

您的请求非常有选择性,不包含完整的组合示例alt_double_left但未shift_double_left列出

我做了什么来为你创建一个例外列表......

变量

$a = array ( // actions
        'left' => 'LEFT',
        'middle' => 'MIDDLE',
        'right' => 'RIGHT' 
);

$m = array ( // modifiers
        'ctrl' => 'CTRL',
        'alt' => 'ALT',
        'shift' => 'SHIFT',
        'double' => 'DOUBLE' 
);

$exceptions = array (
        array (
                "shift",
                "double" 
        ) ,

        array (
                "double",
                "ctrl"
        ),


        array (
                "double",
                "alt"
        )
);

$mc = power_perms ( array_keys ( $m ) );
$options = array ();

环形

echo "<pre>";

foreach ( $a as $aKey => $aValue ) {
    $options [$aValue] = isset ( $options [$aKey] ) ? $options [$aKey] : array ();
    foreach ( $mc as $mKey => $mValue ) {
        $cKey = implode ( "_", $mValue );
        $cKey .= "_" . $aKey;

        $cValue = implode ( "+", $mValue );
        $cValue = strtoupper ( $cValue . "+" . $aValue );
        if (eCheck ( $exceptions, $cKey )) {
            continue;
        }
        $options [$aValue] [$cKey] = $cValue;

    }
}

print_r ( $options );

功能

function eCheck($exceptions, $cKey) {

    foreach ( $exceptions as $eValue ) {

        if (strpos ( $cKey, "{$eValue[0]}_{$eValue[1]}" ) !== false) {
            return true;
        }
        if (strpos ( $cKey, "{$eValue[1]}_{$eValue[0]}" ) !== false) {
            return true;
        }

    }

    return false;
}
function power_perms($arr) {

    $power_set = power_set ( $arr );
    $result = array ();
    foreach ( $power_set as $set ) {
        $perms = perms ( $set );
        $result = array_merge ( $result, $perms );
    }
    return $result;
}

function power_set($in, $minLength = 1) {

    $count = count ( $in );
    $members = pow ( 2, $count );
    $return = array ();
    for($i = 0; $i < $members; $i ++) {
        $b = sprintf ( "%0" . $count . "b", $i );
        $out = array ();
        for($j = 0; $j < $count; $j ++) {
            if ($b {$j} == '1')
                $out [] = $in [$j];
        }
        if (count ( $out ) >= $minLength) {
            $return [] = $out;
        }
    }

    // usort($return,"cmp"); //can sort here by length
    return $return;
}

function factorial($int) {
    if ($int < 2) {
        return 1;
    }

    for($f = 2; $int - 1 > 1; $f *= $int --)
        ;

    return $f;
}

function perm($arr, $nth = null) {

    if ($nth === null) {
        return perms ( $arr );
    }

    $result = array ();
    $length = count ( $arr );

    while ( $length -- ) {
        $f = factorial ( $length );
        $p = floor ( $nth / $f );
        $result [] = $arr [$p];
        array_delete_by_key ( $arr, $p );
        $nth -= $p * $f;
    }

    $result = array_merge ( $result, $arr );
    return $result;
}

function perms($arr) {
    $p = array ();
    for($i = 0; $i < factorial ( count ( $arr ) ); $i ++) {
        $p [] = perm ( $arr, $i );
    }
    return $p;
}

function array_delete_by_key(&$array, $delete_key, $use_old_keys = FALSE) {

    unset ( $array [$delete_key] );

    if (! $use_old_keys) {
        $array = array_values ( $array );
    }

    return TRUE;
}

输出

Array
(
    [LEFT] => Array
        (
            [double_left] => DOUBLE+LEFT
            [shift_left] => SHIFT+LEFT
            [alt_left] => ALT+LEFT
            [alt_shift_left] => ALT+SHIFT+LEFT
            [shift_alt_left] => SHIFT+ALT+LEFT
            [ctrl_left] => CTRL+LEFT
            [ctrl_shift_left] => CTRL+SHIFT+LEFT
            [shift_ctrl_left] => SHIFT+CTRL+LEFT
            [ctrl_alt_left] => CTRL+ALT+LEFT
            [alt_ctrl_left] => ALT+CTRL+LEFT
            [ctrl_alt_shift_left] => CTRL+ALT+SHIFT+LEFT
            [ctrl_shift_alt_left] => CTRL+SHIFT+ALT+LEFT
            [alt_ctrl_shift_left] => ALT+CTRL+SHIFT+LEFT
            [alt_shift_ctrl_left] => ALT+SHIFT+CTRL+LEFT
            [shift_ctrl_alt_left] => SHIFT+CTRL+ALT+LEFT
            [shift_alt_ctrl_left] => SHIFT+ALT+CTRL+LEFT
        )

    [MIDDLE] => Array
        (
            [double_middle] => DOUBLE+MIDDLE
            [shift_middle] => SHIFT+MIDDLE
            [alt_middle] => ALT+MIDDLE
            [alt_shift_middle] => ALT+SHIFT+MIDDLE
            [shift_alt_middle] => SHIFT+ALT+MIDDLE
            [ctrl_middle] => CTRL+MIDDLE
            [ctrl_shift_middle] => CTRL+SHIFT+MIDDLE
            [shift_ctrl_middle] => SHIFT+CTRL+MIDDLE
            [ctrl_alt_middle] => CTRL+ALT+MIDDLE
            [alt_ctrl_middle] => ALT+CTRL+MIDDLE
            [ctrl_alt_shift_middle] => CTRL+ALT+SHIFT+MIDDLE
            [ctrl_shift_alt_middle] => CTRL+SHIFT+ALT+MIDDLE
            [alt_ctrl_shift_middle] => ALT+CTRL+SHIFT+MIDDLE
            [alt_shift_ctrl_middle] => ALT+SHIFT+CTRL+MIDDLE
            [shift_ctrl_alt_middle] => SHIFT+CTRL+ALT+MIDDLE
            [shift_alt_ctrl_middle] => SHIFT+ALT+CTRL+MIDDLE
        )

    [RIGHT] => Array
        (
            [double_right] => DOUBLE+RIGHT
            [shift_right] => SHIFT+RIGHT
            [alt_right] => ALT+RIGHT
            [alt_shift_right] => ALT+SHIFT+RIGHT
            [shift_alt_right] => SHIFT+ALT+RIGHT
            [ctrl_right] => CTRL+RIGHT
            [ctrl_shift_right] => CTRL+SHIFT+RIGHT
            [shift_ctrl_right] => SHIFT+CTRL+RIGHT
            [ctrl_alt_right] => CTRL+ALT+RIGHT
            [alt_ctrl_right] => ALT+CTRL+RIGHT
            [ctrl_alt_shift_right] => CTRL+ALT+SHIFT+RIGHT
            [ctrl_shift_alt_right] => CTRL+SHIFT+ALT+RIGHT
            [alt_ctrl_shift_right] => ALT+CTRL+SHIFT+RIGHT
            [alt_shift_ctrl_right] => ALT+SHIFT+CTRL+RIGHT
            [shift_ctrl_alt_right] => SHIFT+CTRL+ALT+RIGHT
            [shift_alt_ctrl_right] => SHIFT+ALT+CTRL+RIGHT
        )

)

演示链接 http://codepad.viper-7.com/WzLQk8

于 2012-04-12T22:59:39.257 回答
0

我最终弄清楚了。我对 strpos() 和 explode('_'...) 的测试并不完全满意,但它可以工作并且可以满足我的需要。

http://ideone.com/1WDOp

<?php
function custombuttons_generate_children(&$options, $a, $m, $k) {
  $mcount = count($m);
  if (empty($options[$a[$k]])) {
    foreach ($m as $key => $label) {
      $new_key = implode('_', array($k, $key));
      $new_label = implode('+', array($label, $a[$k]));
      $options[$a[$k]][$new_key] = $new_label;
    }
  }
  else {
    foreach ($options[$a[$k]] as $key => $label) {
      foreach ($m as $mkey => $mlabel) {
        if (!strpos($key, '_' . $mkey)) {
          $new_key = implode('_', array($key, $mkey));
          $new_label = implode('+', array($mlabel, $label));
          $options[$a[$k]][$new_key] = $new_label;
        }
      }
    }
  }
  $last = end(array_keys($options[$a[$k]]));
  if (count(explode('_', $last)) !== $mcount) {
    custombuttons_generate_children($options, $a, $m, $k);
  }
}

function custombuttons_action_options_list() {
  $a = array(
    'left' => 'LEFT',
    'middle' => 'MIDDLE',
    'right' => 'RIGHT',
  );
  $m = array( // modifiers
    'ctrl' => 'CTRL',
    'alt' => 'ALT',
    'shift' => 'SHIFT',
    'double' => 'DOUBLE',
  );
  foreach ($a as $key => $label) {
    $options[$key] = $label;
    $options[$label] = array();
    custombuttons_generate_children($options, $a, $m, $key);
  }
  return $options;
}
$options = custombuttons_action_options_list();
?>

输出:

Array
(
    [left] => LEFT
    [LEFT] => Array
        (
            [left_ctrl] => CTRL+LEFT
            [left_alt] => ALT+LEFT
            [left_shift] => SHIFT+LEFT
            [left_double] => DOUBLE+LEFT
            [left_ctrl_alt] => ALT+CTRL+LEFT
            [left_ctrl_shift] => SHIFT+CTRL+LEFT
            [left_ctrl_double] => DOUBLE+CTRL+LEFT
            [left_alt_ctrl] => CTRL+ALT+LEFT
            [left_alt_shift] => SHIFT+ALT+LEFT
            [left_alt_double] => DOUBLE+ALT+LEFT
            [left_shift_ctrl] => CTRL+SHIFT+LEFT
            [left_shift_alt] => ALT+SHIFT+LEFT
            [left_shift_double] => DOUBLE+SHIFT+LEFT
            [left_double_ctrl] => CTRL+DOUBLE+LEFT
            [left_double_alt] => ALT+DOUBLE+LEFT
            [left_double_shift] => SHIFT+DOUBLE+LEFT
            [left_ctrl_alt_shift] => SHIFT+ALT+CTRL+LEFT
            [left_ctrl_alt_double] => DOUBLE+ALT+CTRL+LEFT
            [left_ctrl_shift_alt] => ALT+SHIFT+CTRL+LEFT
            [left_ctrl_shift_double] => DOUBLE+SHIFT+CTRL+LEFT
            [left_ctrl_double_alt] => ALT+DOUBLE+CTRL+LEFT
            [left_ctrl_double_shift] => SHIFT+DOUBLE+CTRL+LEFT
            [left_alt_ctrl_shift] => SHIFT+CTRL+ALT+LEFT
            [left_alt_ctrl_double] => DOUBLE+CTRL+ALT+LEFT
            [left_alt_shift_ctrl] => CTRL+SHIFT+ALT+LEFT
            [left_alt_shift_double] => DOUBLE+SHIFT+ALT+LEFT
            [left_alt_double_ctrl] => CTRL+DOUBLE+ALT+LEFT
            [left_alt_double_shift] => SHIFT+DOUBLE+ALT+LEFT
            [left_shift_ctrl_alt] => ALT+CTRL+SHIFT+LEFT
            [left_shift_ctrl_double] => DOUBLE+CTRL+SHIFT+LEFT
            [left_shift_alt_ctrl] => CTRL+ALT+SHIFT+LEFT
            [left_shift_alt_double] => DOUBLE+ALT+SHIFT+LEFT
            [left_shift_double_ctrl] => CTRL+DOUBLE+SHIFT+LEFT
            [left_shift_double_alt] => ALT+DOUBLE+SHIFT+LEFT
            [left_double_ctrl_alt] => ALT+CTRL+DOUBLE+LEFT
            [left_double_ctrl_shift] => SHIFT+CTRL+DOUBLE+LEFT
            [left_double_alt_ctrl] => CTRL+ALT+DOUBLE+LEFT
            [left_double_alt_shift] => SHIFT+ALT+DOUBLE+LEFT
            [left_double_shift_ctrl] => CTRL+SHIFT+DOUBLE+LEFT
            [left_double_shift_alt] => ALT+SHIFT+DOUBLE+LEFT
        )

    [middle] => MIDDLE
    [MIDDLE] => Array
        (
            [middle_ctrl] => CTRL+MIDDLE
            [middle_alt] => ALT+MIDDLE
            [middle_shift] => SHIFT+MIDDLE
            [middle_double] => DOUBLE+MIDDLE
            [middle_ctrl_alt] => ALT+CTRL+MIDDLE
            [middle_ctrl_shift] => SHIFT+CTRL+MIDDLE
            [middle_ctrl_double] => DOUBLE+CTRL+MIDDLE
            [middle_alt_ctrl] => CTRL+ALT+MIDDLE
            [middle_alt_shift] => SHIFT+ALT+MIDDLE
            [middle_alt_double] => DOUBLE+ALT+MIDDLE
            [middle_shift_ctrl] => CTRL+SHIFT+MIDDLE
            [middle_shift_alt] => ALT+SHIFT+MIDDLE
            [middle_shift_double] => DOUBLE+SHIFT+MIDDLE
            [middle_double_ctrl] => CTRL+DOUBLE+MIDDLE
            [middle_double_alt] => ALT+DOUBLE+MIDDLE
            [middle_double_shift] => SHIFT+DOUBLE+MIDDLE
            [middle_ctrl_alt_shift] => SHIFT+ALT+CTRL+MIDDLE
            [middle_ctrl_alt_double] => DOUBLE+ALT+CTRL+MIDDLE
            [middle_ctrl_shift_alt] => ALT+SHIFT+CTRL+MIDDLE
            [middle_ctrl_shift_double] => DOUBLE+SHIFT+CTRL+MIDDLE
            [middle_ctrl_double_alt] => ALT+DOUBLE+CTRL+MIDDLE
            [middle_ctrl_double_shift] => SHIFT+DOUBLE+CTRL+MIDDLE
            [middle_alt_ctrl_shift] => SHIFT+CTRL+ALT+MIDDLE
            [middle_alt_ctrl_double] => DOUBLE+CTRL+ALT+MIDDLE
            [middle_alt_shift_ctrl] => CTRL+SHIFT+ALT+MIDDLE
            [middle_alt_shift_double] => DOUBLE+SHIFT+ALT+MIDDLE
            [middle_alt_double_ctrl] => CTRL+DOUBLE+ALT+MIDDLE
            [middle_alt_double_shift] => SHIFT+DOUBLE+ALT+MIDDLE
            [middle_shift_ctrl_alt] => ALT+CTRL+SHIFT+MIDDLE
            [middle_shift_ctrl_double] => DOUBLE+CTRL+SHIFT+MIDDLE
            [middle_shift_alt_ctrl] => CTRL+ALT+SHIFT+MIDDLE
            [middle_shift_alt_double] => DOUBLE+ALT+SHIFT+MIDDLE
            [middle_shift_double_ctrl] => CTRL+DOUBLE+SHIFT+MIDDLE
            [middle_shift_double_alt] => ALT+DOUBLE+SHIFT+MIDDLE
            [middle_double_ctrl_alt] => ALT+CTRL+DOUBLE+MIDDLE
            [middle_double_ctrl_shift] => SHIFT+CTRL+DOUBLE+MIDDLE
            [middle_double_alt_ctrl] => CTRL+ALT+DOUBLE+MIDDLE
            [middle_double_alt_shift] => SHIFT+ALT+DOUBLE+MIDDLE
            [middle_double_shift_ctrl] => CTRL+SHIFT+DOUBLE+MIDDLE
            [middle_double_shift_alt] => ALT+SHIFT+DOUBLE+MIDDLE
        )

    [right] => RIGHT
    [RIGHT] => Array
        (
            [right_ctrl] => CTRL+RIGHT
            [right_alt] => ALT+RIGHT
            [right_shift] => SHIFT+RIGHT
            [right_double] => DOUBLE+RIGHT
            [right_ctrl_alt] => ALT+CTRL+RIGHT
            [right_ctrl_shift] => SHIFT+CTRL+RIGHT
            [right_ctrl_double] => DOUBLE+CTRL+RIGHT
            [right_alt_ctrl] => CTRL+ALT+RIGHT
            [right_alt_shift] => SHIFT+ALT+RIGHT
            [right_alt_double] => DOUBLE+ALT+RIGHT
            [right_shift_ctrl] => CTRL+SHIFT+RIGHT
            [right_shift_alt] => ALT+SHIFT+RIGHT
            [right_shift_double] => DOUBLE+SHIFT+RIGHT
            [right_double_ctrl] => CTRL+DOUBLE+RIGHT
            [right_double_alt] => ALT+DOUBLE+RIGHT
            [right_double_shift] => SHIFT+DOUBLE+RIGHT
            [right_ctrl_alt_shift] => SHIFT+ALT+CTRL+RIGHT
            [right_ctrl_alt_double] => DOUBLE+ALT+CTRL+RIGHT
            [right_ctrl_shift_alt] => ALT+SHIFT+CTRL+RIGHT
            [right_ctrl_shift_double] => DOUBLE+SHIFT+CTRL+RIGHT
            [right_ctrl_double_alt] => ALT+DOUBLE+CTRL+RIGHT
            [right_ctrl_double_shift] => SHIFT+DOUBLE+CTRL+RIGHT
            [right_alt_ctrl_shift] => SHIFT+CTRL+ALT+RIGHT
            [right_alt_ctrl_double] => DOUBLE+CTRL+ALT+RIGHT
            [right_alt_shift_ctrl] => CTRL+SHIFT+ALT+RIGHT
            [right_alt_shift_double] => DOUBLE+SHIFT+ALT+RIGHT
            [right_alt_double_ctrl] => CTRL+DOUBLE+ALT+RIGHT
            [right_alt_double_shift] => SHIFT+DOUBLE+ALT+RIGHT
            [right_shift_ctrl_alt] => ALT+CTRL+SHIFT+RIGHT
            [right_shift_ctrl_double] => DOUBLE+CTRL+SHIFT+RIGHT
            [right_shift_alt_ctrl] => CTRL+ALT+SHIFT+RIGHT
            [right_shift_alt_double] => DOUBLE+ALT+SHIFT+RIGHT
            [right_shift_double_ctrl] => CTRL+DOUBLE+SHIFT+RIGHT
            [right_shift_double_alt] => ALT+DOUBLE+SHIFT+RIGHT
            [right_double_ctrl_alt] => ALT+CTRL+DOUBLE+RIGHT
            [right_double_ctrl_shift] => SHIFT+CTRL+DOUBLE+RIGHT
            [right_double_alt_ctrl] => CTRL+ALT+DOUBLE+RIGHT
            [right_double_alt_shift] => SHIFT+ALT+DOUBLE+RIGHT
            [right_double_shift_ctrl] => CTRL+SHIFT+DOUBLE+RIGHT
            [right_double_shift_alt] => ALT+SHIFT+DOUBLE+RIGHT
        )

)

我稍微重新排序了键/标签,但这并没有真正改变解决方案。

于 2012-04-13T06:00:40.590 回答
0

这应该工作

foreach($a as $key=>$val){
    $options[$key]=$val;
    $m_temp=$m;
    while(is_array($m_temp)){
        $options[$val][implode('_', $m_temp).'_'.$key] = implode('_', array_value($m_temp)).'_'.$val;
        $m_temp=array_pop($m_temp);
    }
    $m=$m_temp;
}
于 2012-04-12T23:01:20.273 回答