php - Заменить точную часть строки пользователя с 2 или более подстрок также из ввода пользователя - как это сделать? - PullRequest
0 голосов
/ 23 октября 2018

Я создаю веб-приложение, в котором пользователь вводит специальный вид кода (см. Ниже), который мой сценарий «декодирует» и создает отдельные варианты кода, а затем отправляет каждый из этого кода в запрос SQL.На данный момент я застрял в части, где коды должны преобразовать это:

 A1 B2 - C3 + D4 / E5 / E6 C3 / A5

в эти (интерпретируя косую черту "/" как ИЛИ):

 A1 B2 - C3 + D4 C3
 A1 B2 - C3 + E5 C3
 A1 B2 - C3 + E6 C3
 A1 B2 - C3 + D4 A5
 A1 B2 - C3 + E5 A5
 A1 B2 - C3 + E6 A5

Это то, что яполучил пока:

<?php

// User input
$input = "A1 B2 - C3 + D4 / E5 / E6 C3 / A5";
print_r($input);

// Check how many times user input have "/" (returns INT in $occurencesOfOR and makes complex array $matches of matched substrings)
$occurencesOfOR = preg_match_all("/(?: \/ )?(?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]? \/ (?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]?(?: \/ (?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]?)*/", $input, $matches);
print_r($occurencesOfOR);

// Replacing places of matched pattern with X
$dummyCode = "X";
$inputStripped = preg_replace("/(?: \/ )?(?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]? \/ (?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]?(?: \/ (?:[A-IK-Za-ik-z]|Aa)[1-9][0-9]{0,2}[A-Za-z]?)*/", $dummyCode, $input);
print_r($inputStripped);

print_r($matches);

// Creating simple array with individual OR codes
$orCodesArray = [];
foreach ($matches[0] as $match) {
    array_push($orCodesArray, $match);
}

print_r($orCodesArray);

// Creating multidimensional array from individual codes created by preg_split()
$individualCodesSubarrays = [];
foreach ($orCodesArray as $code) {
    $codeSet = preg_split("/ \/ /", $code);
    array_push($individualCodesSubarrays, $codeSet);
}

print_r($individualCodesSubarrays);

// Count how many subarrays has $individualCodesArray (returns INT)
$counterOfArrays = count($individualCodesSubarrays);
echo $counterOfArrays;

// Getting position of X-es in stripped user input
$lastPos = 0;
$positions = [];
$position = "";
while (($lastPos = strpos($inputStripped, $dummyCode, $lastPos)) !== false) {
    $positions[] = $lastPos;
    $lastPos = $lastPos + strlen($dummyCode);
}
foreach ($positions as $position) {
    echo $position."\n";
}

Но оттуда я не знаю, как продолжать дальше.Я не могу найти решение, как создать функцию, которая заменит 1-е X каждым из D4 / E5 / E6 и 2-е X каждым из C3 / A5, чтобы создать все возможные комбинации, как указано выше.Любая помощь приветствуется.

ОБНОВЛЕНИЕ

Мне удалось сделать это, но все еще не удается заставить его работать.

 // Addition to the upper code at the end
$inputStripped2 = [];
for ($c=0; $c < $counterOfArrays; $c++) {
$individualCodesSubrray = $individualCodesSubarrays[$c];
print_r($individualCodesSubrray);
$countCodes = count($individualCodesSubrray);
echo $countCodes."\n";
for ($x=0; $x < $countCodes; $x++) {
    $dummyCodeX = "X".$c;
    array_push($inputStripped2, str_replace($dummyCodeX, $individualCodesSubrray[$x], $inputStripped));
    }
print_r($inputStripped2);
}

1 Ответ

0 голосов
/ 23 октября 2018

Один из способов добиться желаемого - сначала разбить строку на один пробел (самостоятельно), '+' или '-', например,

$input = "A1 B2 - C3 + D4 / E5 / E6 C3 / A5";
$parts = preg_split('/(?<=[A-Za-z0-9])\s+(?=[A-IK-Za-ik-z])|\s+([+-])\s+/', $input, -1, PREG_SPLIT_DELIM_CAPTURE);

. Это дает:

Array ( 
    [0] => A1
    [1] => B2
    [2] => -
    [3] => C3
    [4] => +
    [5] => D4 / E5 / E6
    [6] => C3 / A5 
)

Эти значения могут быть затем разделены на / с использованием:

foreach ($parts as &$part) {
    $part = preg_split('#\s+/\s+#', $part);
}

Это дает следующий массив массивов:

Array ( 
    [0] => Array ( 
        [0] => A1
    )
    [1] => Array (
        [0] => B2
    )
    [2] => Array (
        [0] => - 
    )
    [3] => Array (
        [0] => C3
    )
    [4] => Array (
        [0] => +
    )
    [5] => Array (
        [0] => D4
        [1] => E5
        [2] => E6
    )
    [6] => Array (
        [0] => C3
        [1] => A5
    ) 
)

Теперь вы можете взятьперекрестные произведения этих массивов, используя array_reduce и функцию, подобную этой:

function cross_product($array, $value) {
    $output = array();
    foreach ($array as $arr) {
        foreach ($value as $val) {
            $output[] = array_merge($arr, array($val));
        }
    }
    return $output;
}

$init = array_map(function ($v) { return array($v); }, array_shift($parts));
$outputs = array_reduce($parts, 'cross_product', array($init));

Наконец, вы можете вывести взорванные версии каждого из массивов $outputs, чтобы получить желаемый результат:

foreach ($outputs as $output) {
    echo implode(' ', $output) . "\n";
}

Выход:

A1 B2 - C3 + D4 C3 
A1 B2 - C3 + D4 A5
A1 B2 - C3 + E5 C3
A1 B2 - C3 + E5 A5
A1 B2 - C3 + E6 C3
A1 B2 - C3 + E6 A5

В качестве альтернативы для ввода "A1 / B2 - C3 + D4 / E5 / E6 C3 + A5" вы получите:

A1 - C3 + D4 C3 + A5 
A1 - C3 + E5 C3 + A5 
A1 - C3 + E6 C3 + A5 
B2 - C3 + D4 C3 + A5 
B2 - C3 + E5 C3 + A5 
B2 - C3 + E6 C3 + A5

Демо на 3v4l.org

...