Php n Dizilerin değerlerini birleştirmek

4 Cevap php

Her kelime sayısı bilinmeyen içeren diziler bilinmeyen bir dizi var. Ben kelimelerin olası tüm varyasyonları son dizi saklanır, böylece her listeden değerlerini birleştirmek istiyorum.

Örneğin, dizi 1 içerir:

dog
cat

ve dizi 2 içerir:

food
tooth

ve dizi 3 içerir:

car
bike

Ben çıkış olmak istiyorum:

dog food car
dog food bike
dog tooth car
dog tooth bike
cat food car
cat food bike
cat tooth car
cat tooth bike

Orada fazla 3 listeleri olabilir, ve her liste büyük olasılıkla en fazla 2 kelime olacak.

PHP bunu yapmak istiyorum.

Muhtemelen en etkin kaynak yöntem olmasa da, ben listeleri numarasını biliyorsanız bunu biliyorum. Ama dizilerin numarasını biliyorsanız foreach eserlerini döngüler iç içe. Ne yoksa? Ve diyelim, 100 deyişle her 100 diziler vardır, eğer çalışmaya devam edeceğini, bu sorunu çözmek için bazı yöntemler nelerdir. Ya da 1000?

Teşekkürler!

4 Cevap

Sen bir diziye bütün kelime diziler koymak ve böyle bir recursive işlevini kullanabilirsiniz:

function concat(array $array) {
    $current = array_shift($array);
    if(count($array) > 0) {
        $results = array();
        $temp = concat($array);
        foreach($current as $word) {
          foreach($temp as $value) {
            $results[] =  $word . ' ' . $value;
          }
        }
        return $results;           
    }
    else {
       return $current;
    }
}

$a = array(array('dog', 'cat'), array('food', 'tooth'), array('car', 'bike'));

print_r(concat($a));

Hangi döndürür:

Array
(
    [0] => dog food car
    [1] => dog food bike
    [2] => dog tooth car
    [3] => dog tooth bike
    [4] => cat food car
    [5] => cat food bike
    [6] => cat tooth car
    [7] => cat tooth bike
)

Ama çıkış dizi çok büyük olacak gibi, bu büyük diziler için kötü davranır sanırım.


Bu etrafında almak doğrudan çıkış kombinasyonları olabilir, benzer bir yaklaşım kullanarak:

function concat(array $array, $concat = '') {
    $current = array_shift($array);

    $current_strings = array();

    foreach($current as $word) {
            $current_strings[] = $concat . ' ' . $word;
    }

    if(count($array) > 0) {
        foreach($current_strings as $string) {
            concat($array, $string);
        }       
    }
    else {
      foreach($current_strings as $string) {
          echo $string . PHP_EOL;
      }   
    }
}

concat(array(array('dog', 'cat'), array('food', 'tooth'), array('car', 'bike')));

Verir:

dog food car
dog food bike
dog tooth car
dog tooth bike
cat food car
cat food bike
cat tooth car
cat tooth bike

Bu yaklaşımla, "alt-concatinations" almak da kolaydır. Sadece concat($array, $string); önce echo $string . PHP_EOL; takıp çıktı:

 dog
 dog food
 dog food car
 dog food bike
 dog tooth
 dog tooth car
 dog tooth bike
 cat
 cat food
 cat food car
 cat food bike
 cat tooth
 cat tooth car
 cat tooth bike

Sen 0 arasındaki her tamsayı için yani sonuç kümesinin elemanları, .... (eleman sayısı) numaralandırabilir -1 (yani doğal bir düzen vardır) dönmek için hangi elemanı söyleyebilirim. Verilen Örneğin:

0 => array1[0], array2[0], array3[0]
1 => array1[0], array2[0], array3[1]
2 => array1[0], array2[1], array3[0]
7 => array1[1], array2[1], array3[1]

Tüm ihtiyacınız olan bir (tamsayı) endeksi n ve n (doğal sıralı) kümesinin eleman inci endeksi "çevirir" bir işlevdir. Sadece mevcut durumunu saklamak için bir tamsayı gerekir çünkü birçok / Büyük diziler olduğunda bellek tüketimi "patlayabilir" değildir. Chris yaptığı açıklamada söylediği gibi (küçük kümeleri kullanırken), düşük bellek tüketimi için hızını ticaret. (Bence-rağmen yolu php uygulanmaktadır-bu aynı zamanda bir makul hızlı bir çözümdür.)

$array1 = array('dog', 'cat');
$array2 = array('food', 'tooth');
$array3 = array('car', 'bike');

function foo( $key /* , ... */ ) {
  $params = func_get_args();
  $rv = array();

  $key = array_shift($params);
  $i=count($params);

  while( 0 < $i-- ) {
    array_unshift($rv, $params[$i][ $key % count($params[$i]) ]);
    $key = (int)($key / count($params[$i]));
  }
  return $rv;
}

for($i=0; $i<8; $i++) {
  $a = foo($i, $array1, $array2, $array3);
  echo join(', ', $a), "\n";
}

Bunu uygulamak için kullanabilirsiniz örneğin bir Iterator, a SeekableIterator ya da belki de, bir ArrayAccess (ve böylece bir {gibi özyinelemeli çözeltiler, almost ile karşılaştırıldığında kontrol tersine çevrilmesi [(4)]}) Python ya da Ruby

<?php
$array1 = array('dog', 'cat', 'mouse', 'bird');
$array2 = array('food', 'tooth', 'brush', 'paste');
$array3 = array('car', 'bike', 'plane', 'shuttlecraft');
$f = new Foo($array1, $array2, $array3);
foreach($f as $e) {
  echo join(', ', $e), "\n";
}

class Foo implements Iterator {
  protected $data = null;
  protected $limit = null;
  protected $current = null;

  public function __construct(/* ... */ ) {  
    $params = func_get_args();
    // add parameter arrays in reverse order so we can use foreach() in current()
    // could use array_reverse(), but you might want to check is_array() for each element.
    $this->data = array();
    foreach($params as $p) {
      // <-- add: test is_array() for each $p  -->
      array_unshift($this->data, $p);
    }
    $this->current = 0;
    // there are |arr1|*|arr2|...*|arrN| elements in the result set
    $this->limit = array_product(array_map('count', $params));
  }

  public  function current() {
    /* this works like a baseX->baseY converter (e.g. dechex() )
       the only difference is that each "position" has its own number of elements/"digits"
    */
    // <-- add: test this->valid() -->
    $rv = array();
    $key = $this->current;
    foreach( $this->data as $e) {
      array_unshift( $rv, $e[$key % count($e)] );
      $key = (int)($key/count($e));
    }
    return $rv;
  }

  public function key() { return $this->current;  }
  public function next() { ++$this->current; }
  public function rewind () { $this->current = 0; }
  public function valid () { return $this->current < $this->limit; }
}

baskılar

dog, food, car
dog, food, bike
dog, food, plane
dog, food, shuttlecraft
dog, tooth, car
dog, tooth, bike
[...]
bird, paste, bike
bird, paste, plane
bird, paste, shuttlecraft

(Dizi ;-) ok gibi görünüyor)

Ben büyük bir kelime listeleri bu test değil ama orta büyüklükteki listelerde oldukça hızlı ve muhtemelen bellek sınırı sorunlara neden oluyor (ben yanılıyorsam düzeltin lütfen) düşünüyorum özyineleme kullanmak değildir:

$lines = array('');

foreach ($arrays as $array) {

  $old_lines = $lines;
  $lines = array();

  foreach ($array as $word) {

    foreach ($old_lines as $line) {

      $lines[] = trim($line .' '. $word);

    } // foreach

  } // foreach

} // foreach

Benim almak

class Combinator
{
     protected $words;
     protected $combinator;

     public function __construct($words, $combinator = null)
     {
         $this->words = $words;
         $this->combinator = $combinator;
     }

     public function run($combo = '')
     {
         foreach($this->words as $word) {
             if($this->combinator !== null) {
                 $this->combinator->run("$combo $word"); 
             } else {
                 echo "$combo $word", PHP_EOL;
             }
         }
     }
}

$c = new Combinator(array('dog', 'cat'), 
                    new Combinator(array('food', 'tooth'),
                                   new Combinator(array('car', 'bike'))));

$c->run();