Я пытаюсь создать функцию для генерации всех возможных комбинаций определенной группы символов и иметь ее переменную в зависимости от длины.
У меня есть функция для создания массива символов, которые я хотел бы, и это прекрасно работает.
function generate_characters($l, $n, $d) {
$r = array();
if ($l === true) {
foreach (range('a', 'z') as $index) {
array_push($r, $index);
}
}
if ($n === true) { array_push($r, '0','1','2','3','4','5','6','7','8','9'); }if ($d === true) { array_push($r, '-'); }
return $r;
}
Затем мне нужно, чтобы он создал массив всех возможных комбинаций на основе $ length, например, если ‘$ length = 1’, мне нужен следующий массив
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => e
[5] => f
[6] => g
[7] => h
[8] => i
[9] => j
[10] => k
[11] => l
[12] => m
[13] => n
[14] => o
[15] => p
[.... removed some values to save on length ....]
[35] => 9
)
но если ‘$ length = 2’ мне нужно это
Array
(
[0] => aa
[1] => ab
[2] => ac
[3] => ad
[4] => ae
[5] => af
[6] => ag
[7] => ah
[8] => ai
[9] => aj
[.... removed some values to save on length ....]
[1329] => 97
[1330] => 98
[1331] => 99
)
Я пробовал array_walk () и array_walk_recursive (), а также несколько циклов foreach и while, но безрезультатно.
Я могу заставить это работать, вручную делая это для каждой длины, но не с переменной длиной, делая это, но не знаю, как сделать это переменным по длине.
function generate_two($l, $n, $d) {
$r = array();
foreach (generate_characters($l, $n, false) as $v1) {
foreach (generate_characters($l, $n, $d) as $v2) {
array_push($results, "$v1$v2");
}
}
return $r;
}
все это при отсутствии символа «-» в качестве первого символа, хотя я мог бы удалить эти значения после генерации массива, если мне нужно.
Спасибо Дэн
Предполагая, что вы хотите использовать созданный вами массив в качестве массива для добавления в него. Я не понимаю, почему вам нужно работать с определенными символами, отличными от символов в массиве (я могу ошибаться, но это может быть легко адаптировано для этого).
/**
* @param array $array
* @param $length
* @param null $original
* @return array
*/
function generate_values(array $array, $length, $original = null) {
// If length is 1 or less just return the array
if ($length <= 1) {
return $array;
}
// The resulting values array
$result = [];
// Copy the array if original doesn't exist
if (!is_array($original)) {
$original = $array;
}
// Loop over each item and append the original values
foreach($array as $item) {
foreach($original as $character) {
$result[] = $item . $character;
};
}
// Recursively generate values until the length is 1
return generate_values($result, --$length, $original);
}
Чтобы использовать его, вы можете использовать свой генератор.
$characterArray = generate_characters(true, false, false);
$results = generate_values($characterArray, 2);
Я не знаю, является ли это лучшим решением, но:
function generate_characters($length, $n, $d, $array = array()) {
$letters = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9');
$numbers = range(0, 9);
$others = array('-');
if($n == true)
$letters = array_merge($letters, $numbers);
if($d == true)
$letters = array_merge($letters, $others);if(empty($array))
$array = $letters;
if(--$length <= 0)
return $array;
$result = array();
foreach ($array as $value) {
foreach ($letters as $add) {
$result[] = $value.$add;
}
}
return generate_characters($length, $n, $d, $result);
}
echo '<pre>';
print_r(generate_characters(3, true, true));
function generate_characters($l, $n, $d)
{
// Start with an empty list
$r = array();
// Add the letters, if required
if ($l) {
$r = array_merge($r, range('a', 'z'));
}
// Add the digits, if required
if ($n) {
$r = array_merge($r, range('0', '9'));
}
// Add special characters, if required
if ($d) {
$r[] = '-';
}
return $r;
}/**
* Generate all combinations of $len characters using the characters
* from a given list
*
* @param array $chars the list of characters to use
* @param int $len the length of strings to generate
* @return array
*/
function generate_combinations(array $chars, $len)
{
// $len <= 0: this is an error
// $len == 1: the input list is the output
if ($len <= 1) {
return $chars;
}
// Compute the output here
$result = array();
// Recursively compute the list of characters of length $len - 1
$partial = generate_combinations($chars, $len - 1);
// Append each entry from the input list to each string of length $len - 1 computed on the previous step
foreach ($partial as $head) {
foreach ($chars as $tail) {
// Put the combination in the output list
$result[] = $head.$tail;
}
}
// This is the list of all strings of length $len over the list $chars
return $result;
}
Нет необходимости звонить generate_characters()
опять и опять. Учитывая одинаковые аргументы, он всегда возвращает один и тот же список символов. Сохраните его в переменной, используйте переменную дальше.
$chars = generate_characters(TRUE, FALSE, TRUE);
$comb2 = generate_combinations($chars, 2);
$comb5 = generate_combinations($chars, 5);
Хотя теоретически правильно, генерация всех комбинаций совершенно бесполезна в реальной жизни. Количество комбинаций увеличивается в геометрической прогрессии, и вскоре ваш скрипт будет использовать всю доступную память для хранения списка.
Я протестировал приведенный выше код, и PHP 5.6 потребовалось более 2 ГБ памяти для генерации всех комбинаций из 5 символов (с использованием букв + тире). PHP 7 использует память лучше, и для этой же задачи ему требуется менее 1 ГБ памяти.
Как вы можете себе представить, невозможно использовать более высокие значения для параметра $len
; даже для $len == 5
перечисленные выше суммы уже огромны.
Если вы хотите комбинацию двух значений массива, вы можете использовать непосредственно этот код. Вам не требуется длина этого массива в вашей функции.
function generateValue($array1, $array2) {
$result = array();
foreach ($array as $value) {
foreach ($original as $value2) {
$result[] = $value.$value2;
}
}
return $result;
}
print_r(generateValue($array1, $array2));