2010-03-25 51 views
19

Tôi đã có vấn đề này uốn tâm trí của tôi trong một thời gian bây giờ (đầu lạnh không giúp được gì!), Về cơ bản tôi có một mảng PHP mà trông giống như ví dụ sau:PHP 2D mảng đầu ra tất cả các kết hợp

$array[0][0] = 'apples'; 
$array[0][1] = 'pears'; 
$array[0][2] = 'oranges'; 

$array[1][0] = 'steve'; 
$array[1][1] = 'bob'; 

Và tôi muốn để có thể tạo ra từ này một bảng với mỗi sự kết hợp có thể trong số này, nhưng không lặp lại bất kỳ kết hợp (không phân biệt vị trí của họ), ví dụ như vậy sẽ này ra

Array 0   Array 1 
apples    steve 
apples    bob 
pears    steve 
pears    bob 

nhưng tôi sẽ như thế này để có thể làm việc với nhiều mảng khác nhau như possib le.

+0

Sẽ có Mảng 2, Array 3, Array N? Hoặc chỉ có hai mảng? –

+0

Xin lỗi vì đã không làm rõ hơn, có thể có mảng 2, mảng 3 đến mảng n. Cảm ơn. – stukerr

+0

Điều bạn cần là một phép nối chéo được thực hiện dễ dàng trong SQL, nhưng cần một số suy nghĩ trong PHP –

Trả lời

20

điều này được gọi là "sản phẩm Descartes", trang người đàn ông php trên mảng http://php.net/manual/en/ref.array.php hiển thị một số triển khai (trong nhận xét).

và đây là chưa nhau:

function array_cartesian() { 
    $_ = func_get_args(); 
    if(count($_) == 0) 
     return array(array()); 
    $a = array_shift($_); 
    $c = call_user_func_array(__FUNCTION__, $_); 
    $r = array(); 
    foreach($a as $v) 
     foreach($c as $p) 
      $r[] = array_merge(array($v), $p); 
    return $r; 
} 

$cross = array_cartesian(
    array('apples', 'pears', 'oranges'), 
    array('steve', 'bob') 
); 

print_r($cross); 
+0

Nội dung tuyệt vời, chỉ là những gì tôi cần. Rất cám ơn – stukerr

+0

cho phép đặt trang thực tại đó: http://php.net/manual/en/ref.array.php :) –

+1

Nếu hàm này tồn tại trong một lớp, bạn có thể muốn thay đổi lệnh gọi user_func như sau: ' $ c = call_user_func_array (mảng ($ this, __ FUNCTION__), $ _); '. Ngoài ra, nó có thể đưa ra một cảnh báo (không phải là một mảng) nếu mảng đầu vào không có kích thước bằng nhau. – Nanne

-2

Trong cơ sở dữ liệu MySQL trong sẽ là như thế này:

SELECT * 
FROM `options`, `groups` 

Đó là tất cả :)

1

này hoạt động Tôi nghĩ rằng - mặc dù sau khi viết nó Tôi nhận ra nó khá giống với những gì người khác đã đặt, nhưng nó cung cấp cho bạn một mảng theo định dạng được yêu cầu. Xin lỗi vì đặt tên biến nghèo.

$output = array(); 
combinations($array, $output); 
print_r($output); 

function combinations ($array, & $output, $index = 0, $p = array()) { 
    foreach ($array[$index] as $i => $name) { 
     $copy = $p; 
     $copy[] = $name; 
     $subIndex = $index + 1; 
     if (isset($array[$subIndex])) { 
      combinations ($array, $output, $subIndex, $copy); 
     } else { 
      foreach ($copy as $index => $name) { 
       if (!isset($output[$index])) { 
        $output[$index] = array(); 
       } 
       $output[$index][] = $name; 
      } 
     } 
    } 
} 
1

@ user187291

tôi sửa đổi này là

function array_cartesian() { 
    $_ = func_get_args(); 
    if (count($_) == 0) 
     return array(); 
    $a = array_shift($_); 
    if (count($_) == 0) 
     $c = array(array()); 
    else 
     $c = call_user_func_array(__FUNCTION__, $_); 
    $r = array(); 
    foreach($a as $v) 
     foreach($c as $p) 
      $r[] = array_merge(array($v), $p); 
    return $r; 
} 

để nó trả về đó hết sức quan trọng mảng rỗng (kết quả tương tự như không kết hợp) khi bạn vượt qua 0 đối số.

Chỉ nhận thấy điều này bởi vì tôi đang sử dụng nó như

$combos = call_user_func_array('array_cartesian', $array_of_arrays); 
1
foreach($parentArray as $value) { 
    foreach($subArray as $value2) { 
     $comboArray[] = array($value, $value2); 
    } 
} 

Đừng phán xét tôi ..

+0

"Tất nhiên nó phải hoạt động khi sizeof ($ array)> = 2." –

0
function array_comb($arrays) 
{ 
    $result = array(); 
    $arrays = array_values($arrays); 
    $sizeIn = sizeof($arrays); 
    $size = $sizeIn > 0 ? 1 : 0; 
    foreach ($arrays as $array) 
     $size = $size * sizeof($array); 
    for ($i = 0; $i < $size; $i ++) 
    { 
     $result[$i] = array(); 
     for ($j = 0; $j < $sizeIn; $j ++) 
      array_push($result[$i], current($arrays[$j])); 
     for ($j = ($sizeIn -1); $j >= 0; $j --) 
     { 
      if (next($arrays[$j])) 
       break; 
      elseif (isset ($arrays[$j])) 
       reset($arrays[$j]); 
     } 
    } 
    return $result; 
} 
3

Sao chép Syom http://www.php.net/manual/en/ref.array.php#54979 nhưng tôi đã điều chỉnh nó để trở thành phiên bản kết hợp:

function array_cartesian($arrays) { 
    $result = array(); 
    $keys = array_keys($arrays); 
    $reverse_keys = array_reverse($keys); 
    $size = intval(count($arrays) > 0); 
    foreach ($arrays as $array) { 
    $size *= count($array); 
    } 
    for ($i = 0; $i < $size; $i ++) { 
    $result[$i] = array(); 
    foreach ($keys as $j) { 
     $result[$i][$j] = current($arrays[$j]); 
    } 
    foreach ($reverse_keys as $j) { 
     if (next($arrays[$j])) { 
     break; 
     } 
     elseif (isset ($arrays[$j])) { 
     reset($arrays[$j]); 
     } 
    } 
    } 
    return $result; 
} 
2

Tôi cần làm như vậy và tôi đã thử các giải pháp trước được đăng ở đây nhưng không thể làm cho chúng hoạt động. Tôi đã lấy mẫu từ anh chàng thông minh này http://www.php.net/manual/en/ref.array.php#54979. Tuy nhiên, mẫu của ông không quản lý khái niệm không có sự kết hợp lặp lại. Vì vậy, tôi đã bao gồm phần đó.Đây là phiên bản sửa đổi của tôi, hy vọng nó sẽ giúp:

$data = array(
     array('apples', 'pears', 'oranges'), 
     array('steve', 'bob') 
    ); 

    $res_matrix = $this->array_cartesian_product($data); 

    foreach ($res_matrix as $res_array) 
    { 
     foreach ($res_array as $res) 
     { 
      echo $res . " - "; 
     } 
     echo "<br/>"; 
    } 


function array_cartesian_product($arrays) 
{ 
    $result = array(); 
    $arrays = array_values($arrays); 

    $sizeIn = sizeof($arrays); 
    $size = $sizeIn > 0 ? 1 : 0; 
    foreach ($arrays as $array) 
     $size = $size * sizeof($array); 
    $res_index = 0; 
    for ($i = 0; $i < $size; $i++) 
    { 
     $is_duplicate = false; 
     $curr_values = array(); 
     for ($j = 0; $j < $sizeIn; $j++) 
     { 
      $curr = current($arrays[$j]); 
      if (!in_array($curr, $curr_values)) 
      { 
       array_push($curr_values , $curr); 
      } 
      else 
      { 
       $is_duplicate = true; 
       break; 
      } 
     } 
     if (!$is_duplicate) 
     { 
      $result[ $res_index ] = $curr_values; 
      $res_index++; 
     } 
     for ($j = ($sizeIn -1); $j >= 0; $j--) 
     { 
      $next = next($arrays[ $j ]); 
      if ($next) 
      { 
       break; 
      } 
      elseif (isset ($arrays[ $j ])) 
      { 
       reset($arrays[ $j ]); 
      } 
     } 
    } 
    return $result; 
} 

Kết quả sẽ là một cái gì đó như thế này:
táo - steve
táo - bob
lê - steve
lê - bob
cam - steve
cam - bob

Nếu bạn mảng dữ liệu là một cái gì đó như thế này:

$data = array(
     array('Amazing', 'Wonderful'), 
     array('benefit', 'offer', 'reward'), 
     array('Amazing', 'Wonderful') 
    ); 

Sau đó, nó sẽ in một cái gì đó như thế này:

tuyệt vời - lợi ích - Wonderful
tuyệt vời - cung cấp - Wonderful
tuyệt vời - khen thưởng - Wonderful
Wonderful - lợi ích - Amazing
Wonderful - cung cấp - Tuyệt vời
Tuyệt vời - phần thưởng - Tuyệt vời

0

Tôi phải kết hợp từ các tùy chọn sản phẩm. Giải pháp này sử dụng đệ quy và làm việc với mảng 2D:

function options_combinations($options) { 
    $result = array(); 
    if (count($options) <= 1) { 
     $option = array_shift($options); 
     foreach ($option as $value) { 
      $result[] = array($value); 
     } 
    } else { 
     $option = array_shift($options); 
     $next_option = options_combinations($options); 
     foreach ($next_option as $next_value) { 
      foreach ($option as $value) { 
       $result[] = array_merge($next_value, array($value)); 
      } 
     } 
    } 
    return $result; 
} 

$options = [[1,2],[3,4,5],[6,7,8,9]]; 
$c = options_combinations($options); 
foreach ($c as $combination) { 
    echo implode(' ', $combination)."\n"; 
} 
0

thực hiện Elegant dựa trên chức năng Python bản địa itertools.product

function direct_product(array ...$arrays) 
{ 
    $result = [[]]; 
    foreach ($arrays as $array) { 
     $tmp = []; 
     foreach ($result as $x) { 
      foreach ($array as $y) { 
       $tmp[] = array_merge($x, [$y]); 
      } 
     } 
     $result = $tmp; 
    } 
    return $result; 
} 
Các vấn đề liên quan