Задать вопрос

Как скомбинировать массивы, чтобы получить все варианты сочетаний их элементов?

Есть 3 массива (но их может быть и 4, 5 и больше), которые содержат slug.
Их этих массивов нужно перекрестно собрать все возможные значения, чтобы получить итоговый URL.
Массивы идут в правильном порядке для формирования URL.

$array1 = [
    'brand-1',
    'brand-2',
];

$array2 = [
    'style-1',
    'style-2',
    'style-3',
];

$array3 = [
    'color-1',
    'color-2',
];

Нужно обойти массивы так, чтобы к значению первого массива подставились все значения из второго и третьего массива по очереди, а затем и из третьего.

Нужно получить:

brand-1/style-1/color-1
brand-1/style-1/color-2
brand-1/style-2/color-1
brand-1/style-2/color-2
brand-1/style-3/color-1
brand-1/style-3/color-2

brand-2/style-1/color-1
brand-2/style-1/color-2
brand-2/style-2/color-1
brand-2/style-2/color-2
brand-2/style-3/color-1
brand-2/style-3/color-2

brand-3/style-1/color-1
brand-3/style-1/color-2
brand-3/style-2/color-1
brand-3/style-2/color-2
brand-3/style-3/color-1
brand-3/style-3/color-2
  • Вопрос задан
  • 207 просмотров
Подписаться 1 Простой 7 комментариев
Решения вопроса 3
0xD34F
@0xD34F
Рекурсия есть:

function combinations($arr = [], ...$arrs) {
  return count($arrs)
    ? array_merge(...array_map(
        fn($n) => array_map(
          fn($m) => [ $n, ...$m ],
          combinations(...$arrs)
        ),
        $arr
      ))
    : array_map(fn($n) => [ $n ], $arr);
}

Рекурсии нет:

function combinations(...$arrs) {
  $result = [];
  $size = array_reduce($arrs, fn($acc, $n) => $acc * count($n), count($arrs) ? 1 : 0);

  for ($i = 0; $i < $size; $i++) {
    $row = [];
    for ($index = $i, $j = count($arrs); $j--;) {
      $row[] = $arrs[$j][$index % count($arrs[$j])];
      $index = intval($index / count($arrs[$j]));
    }
    $result[] = array_reverse($row);
  }

  return $result;
}

Как использовать в вашем случае:

$result = array_map(
  fn($n) => implode('/', $n),
  combinations($array1, $array2, $array3)
);
Ответ написан
Комментировать
toxa82
@toxa82
Вам нужна рекурсивная функция
function slug(string $start, $arrays): array
{
    $result = [];
    $current = array_shift($arrays);
    $isLast = count($arrays) === 0;
    foreach ($current as $value) {
        $path = !empty($start) ? $start . '/' . $value : $value;
        if ($isLast) {
            $result[] = $path;
        } else {
            $result = array_merge($result, slug($path, $arrays));
        }
    }
    return $result;
}
$array1 = [
    'brand-1',
    'brand-2',
    'brand-3',
];
$array2 = [
    'style-1',
    'style-2',
    'style-3',
];
$array3 = [
    'color-1',
    'color-2',
];
var_dump(slug('', [$array1, $array2, $array3]));

array (size=18)
  0 => string 'brand-1/style-1/color-1' (length=23)
  1 => string 'brand-1/style-1/color-2' (length=23)
  2 => string 'brand-1/style-2/color-1' (length=23)
  3 => string 'brand-1/style-2/color-2' (length=23)
  4 => string 'brand-1/style-3/color-1' (length=23)
  5 => string 'brand-1/style-3/color-2' (length=23)
  6 => string 'brand-2/style-1/color-1' (length=23)
  7 => string 'brand-2/style-1/color-2' (length=23)
  8 => string 'brand-2/style-2/color-1' (length=23)
  9 => string 'brand-2/style-2/color-2' (length=23)
  10 => string 'brand-2/style-3/color-1' (length=23)
  11 => string 'brand-2/style-3/color-2' (length=23)
  12 => string 'brand-3/style-1/color-1' (length=23)
  13 => string 'brand-3/style-1/color-2' (length=23)
  14 => string 'brand-3/style-2/color-1' (length=23)
  15 => string 'brand-3/style-2/color-2' (length=23)
  16 => string 'brand-3/style-3/color-1' (length=23)
  17 => string 'brand-3/style-3/color-2' (length=23)
Ответ написан
Комментировать
@Vitsliputsli
Если надо универсально, для любого кол-ва (что сомнительно):
function urlCombinations(...$arrays): array
{
    if (count($arrays) <= 1) {
        return $arrays;
    }
    $urls = [];
    foreach ($arrays[0] as $value1) {
        foreach ($arrays[1] as $value2) {
            $urls[] = "$value1/$value2";
        }
    }
    return urlCombinations($urls, ...array_slice($arrays,2));
}
var_dump(urlCombinations($array1, $array2, $array3));

Но, скорее всего так:
$urls = [];
foreach ($brands as $brand) {
    foreach ($styles as $style) {
        foreach ($colors as $color) {
            $urls[] = "$brand/$style/$color";
        }
    }
}
var_dump($urls);
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы