【问题标题】:PHP: concatenate possible combinations from an arrayPHP:连接数组中的可能组合
【发布时间】:2012-05-07 21:55:52
【问题描述】:

我有一个数组,其中包含不同组合的字符串集/组(在本例中为小写和大写)。我正在尝试循环这个数组 - 使用 php - 并从原始字符串可以组成的所有可能组合中生成新的字符串。

数组如下所示:

Array
(
    [0] => Array
        (
            [0] => ALFA
            [1] => alfa
        )
    [1] => Array
        (
            [0] => BETA
            [1] => beta
        )
    [2] => Array
        (
            [0] => DELTA
            [1] => delta
        )
)

我想要的输出应该是这样的:

ALFA
ALFA BETA
ALFA beta
ALFA DELTA
ALFA delta
ALFA BETA DELTA
ALFA BETA delta
ALFA beta beta
ALFA DELTA BETA
ALFA DELTA beta
ALFA delta BETA
ALFA delta beta
alfa 
alfa BETA
alfa beta
alfa DELTA
alfa delta
alfa BETA DELTA
alfa BETA delta
alfa beta beta
alfa DELTA BETA
alfa DELTA beta
alfa delta BETA
alfa delta beta
BETA
BETA ALFA
BETA alfa
BETA DELTA
BETA delta
BETA ALFA delta
BETA ALFA DELTA
BETA alfa delta
BETA alfa DELTA
BETA DELTA alfa
BETA DELTA ALFA
BETA delta alfa
BETA delta ALFA
beta
beta ALFA
...
...

我花了一整天的时间试图弄清楚这一点,但被卡住了。非常感谢任何输入或帮助,谢谢!

【问题讨论】:

  • 这是一个非常简单的问题,解决方案也很简单,但是让我问你为什么你要这样做?几乎可以肯定,有一种更好的方法可以以这种非常低性能和高内存的方式来完成您想要完成的工作。
  • 您输入预期输出并手动完成您希望脚本自动执行的操作花了多长时间?
  • @Mahmoud:我想要完成的是一个脚本,它接受 1-4 个输入字符串并生成一个包含这些单词所有可能组合的单词列表。每个输入字符串也会有不同的格式,例如大写、小写、大写在前、大写在后等。
  • 您误解了 - 拥有所有不同的字符串组合将有助于解决什么全局
  • 我想用“合格的猜测”密码制作一个单词列表,这样我就可以尝试暴力破解 WPA 路由器。

标签: php loops combinations


【解决方案1】:

您可以存储一个仅包含这些字符串的小写版本的数组,然后将其动态大写(strtoupper 完成这项工作)。

然后使用嵌套的for 循环或递归遍历数组的每个元素和echo 您需要的各种组合(只需跳过在两层迭代(或递归)中位于同一元素上的情况) ))

【讨论】:

    【解决方案2】:

    同意@Mahmoud Al-Qudsi,这似乎是一个奇怪的问题,如果阵列大于微不足道的大小,很容易破坏您的服务器。您确实意识到我们在这里谈论的是阶乘 - 如果您的数组有 10 个元素,那么仅在一种情况下,所有 10 个字符串的排列数就是 10!也就是 350 万 加上大小写版本,加上 9、8 等元素的字符串组合,我们正在谈论非常长的计算。在 10 个元素数组之后,每增加一个元素,计算次数至少乘以 10,即 3500 万与 11、3.5 亿与 12……你会发现偏差。

    【讨论】:

      【解决方案3】:

      使用

      class CartesianProductIterator implements Iterator {
          protected $iterators;
      
          function __construct(array $iters) {
              $this->iterators = $iters;
          }
      
          function rewind() {
              foreach ($this->iterators as $it) {
                  $it->rewind();
              }
          }
      
          function current() {
              $values = array();
              foreach ($this->iterators as $it) {
                  $values[] = $it->current();
              }
              return $values;
          }
      
          function key() {
              return null;
          }
      
          function next() {
              /*      
              loop them in reverse, but exclude first
              why? example, odometer: 55199
              you always check the rightmost digit first to see if incrementing it would roll it over and need to be "rewound" to 0, 
              which causes the digit to the left to increase as well, which may also cause it to roll over as well, and so on...
              looping in reverse operates from right column to the left.
              we dont rewind the first column because if the leftmost column is on its last element and needs to roll over
              then this iterator has reached its end, and so rewind() needs to be explicitly called 
              */
              for ($i = count($this->iterators) - 1; $i > 0; --$i) {
                  $it = $this->iterators[$i];
                  $it->next();
                  if ($it->valid()) {
                      // were done advancing because we found a column that didnt roll over
                      return;
                  } else {
                      $it->rewind();
                  }
              }
      
              //if execution reached here, then all of the columns have rolled over, so we must attempt to roll over the left most column
              $this->iterators[0]->next();
          }
      
          function valid() {
              return $this->iterators[0]->valid();
          }
      }
      

      您可以按如下方式专门使用它

      $iterators = array();
      foreach ($arr as $possibleChoicesForOneSlotInACombo) {
          //we add null as a way indicate "no value" as a choice for this slot
          $possibleChoicesForOneSlotInACombo[] = null;
          $iterators[] = new ArrayIterator($possibleChoicesForOneSlotInACombo);
      }
      
      foreach (new CartesianProductIterator($iterators) as $combo) {
          //filter out the possible nulls that might exist in this combo
          $strings = array_filter($combo, 'is_string');
      
          // make sure something exists, maybe they were all null
          if ($strings) {
              echo join(' ', $strings), "\n";
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-09-28
        • 1970-01-01
        • 1970-01-01
        • 2011-12-22
        • 1970-01-01
        • 1970-01-01
        • 2021-01-17
        • 2011-05-31
        相关资源
        最近更新 更多