Рекурсивный вызов PHP для генерации массива

Или даже вы можете перейти к интерфейсу, считая, что требуется небольшое ограничение:

public interface IControllable
{
    void Move(int step);
    void Backward(int step);
}

public interface ITurnable
{
   void TurnLeft(float angle);
   void TurnRight(float angle);
}

public class Airplane : IControllable, ITurnable
{
   void Move(int step)
   {
       // TODO: Implement code here...
   }
   void Backward(int step)
   {
       // TODO: Implement code here...
   }
   void TurnLeft(float angle)
   {
       // TODO: Implement code here...
   }
   void TurnRight(float angle)
   {
       // TODO: Implement code here...
   }
}

Однако вам придется реализовать все объявление функции как IControllable, так и ITurnable в противном случае произойдет ошибка компилятора. Если вам нужна дополнительная реализация virutal, вам нужно будет пойти abstract class для виртуального метода с interface для чистого виртуального метода.

На самом деле существует разница между функцией interface и abstract функция interface объявляет только функцию, вся функция interface должна быть общедоступной, поэтому нет свойства fancy class, такого как private или protected, поэтому она очень быстрая, а функция abstract - это метод фактического класса без реализация и принудительное выполнение в производном классе, поэтому вы можете поместить private, protected и переменные-члены доступа с функциями abstract, и большую часть времени это медленнее, потому что отношения наследования класса анализируются во время выполнения. (aka vtable)

2
задан SolidSnake 17 January 2019 в 05:50
поделиться

2 ответа

Мне наконец удалось это сделать. это не лучшее решение, но оно работает. Также, если у нас более 10 элементов, процесс начинает замедляться, потому что он умножается каждый раз, когда мы добавляем новый элемент:

public function generateAllCases($arr1, $arr2, $resultArr, &$index, $firstCall = false)
{
    $shifted = false;

    foreach ($arr1 as $elm)
    {
        foreach ($arr2 as $i => $vis)
        {
            if(!$shifted)
            {
                array_shift($arr1);
                $shifted = true;
            }

            if(!isset($resultArr[$index]) || !isset($resultArr[$index][$elm]))
            {
                $resultArr[$index][$elm] = $vis;
            }
            else 
            {
                $prevItem = $resultArr[$index];
                $index++;
                $resultArr[$index] = $prevItem;
                $resultArr[$index][$elm] = $vis;
            }

            $resultArr = $this->generateAllCases($arr1, $arr2, $resultArr, $index);
        }
        break;
    }

    if($firstCall)
    {
        $allResults = [];
        foreach ($resultArr as $k => $v) 
        {
            $allResults[implode('.', $v)] = $v;
        }

        $allResults = array_values($allResults);
        return $allResults;
    }

    return $resultArr;
}

называется так:

$index = 0;
$cases = $rpd->generateAllCases(['a', 'b', 'c'], [true, false], [], $index, true);
0
ответ дан SolidSnake 17 January 2019 в 05:50
поделиться

Кажется, вы ищете все перестановок с повторением всех элементов в $arr2 с длиной числа элементов в $arr1.

Если это так, должно работать следующее:

<?php
declare(strict_types=1);

error_reporting(-1);
ini_set('display_errors', 'On');

function pwr(array $elements, int $k, int $idx = 0, array &$result = []): \Generator
{
    foreach ($elements as $element) {
        $result[$idx] = $element;

        if ($k - $idx > 1) {
            yield from pwr($elements, $k, $idx + 1, $result);
        }
        else {
            yield $result;
        }
    }
}

function gen(array $keys, array $values): \Generator
{
    foreach (pwr($values, \count($keys)) as $set) {
        yield array_combine($keys, $set);
    }
}

// this is just to test the result in a more *visual* way
foreach (gen(range('a', 'j'), [true, false]) as $case) {
    foreach ($case as $k => $v) {
        echo $v ? $k : '_';
    }

    echo "\n";
}

Чтобы избежать проблем с памятью, вы можете использовать yield , но если массив абсолютно необходим, используйте [114 ] .

Очевидно, что это растет очень быстро (\count($arr2) ** \count($arr1)), поэтому будьте осторожны при использовании iterator_to_array.

Демонстрация: https://3v4l.org/l5PRo

0
ответ дан Yoshi 17 January 2019 в 05:50
поделиться
Другие вопросы по тегам:

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