PHP заменит символы всех возможных вариантов

У меня есть символы массива, которые я хочу заменить, но мне нужно сгенерировать все возможности

$lt = array(
'a' => 'ą',
'e' => 'ę',
'i' => 'į',
);

Например, если у меня есть эта строка:

tazeki

Там может быть огромное количество результатов:

tązeki
tazęki
tązęki
tazekį
tązekį
tazękį
tązękį

У меня вопрос, какую формулу использовать для всех вариантов?

2

Решение

Это должно работать для вас, легко и просто:

Что делает этот код?

1. Часть данных

В части данных я просто определяю строку и замену для одного символа с ассоциативным массивом (поиск символа в качестве ключа, замена в качестве значения).

2. getReplacements() функция

Эта функция получает все комбинации символов, которые должны быть заменены в этом формате:

key   = index in the string
value = character

Таким образом, в этом примере кода массив будет выглядеть примерно так:

Array (
[0] => Array (
[1] => a
)
[1] => Array (
[3] => e
)
[2] => Array (
[3] => e
[1] => a
)
[3] => Array (
[5] => i
)
[4] => Array (
[5] => i
[1] => a
)
[5] => Array (
[5] => i
[3] => e
)
[6] => Array (
[5] => i
[3] => e
[1] => a
)

)

Как видите, этот массив содержит все комбинации символов, которые должны быть заменены, в следующем формате:

[0] => Array (
//^^^^^ The entire sub array is the combination which holds the single characters which will be replaced
[1] => a
//^     ^ A single character of the full combination which will be replaced
//| The index of the character in the string (This is that it also works if you have a character multiple times in your string)
// e.g. 1 ->  t *a* z e k i
//            ^  ^  ^ ^ ^ ^
//            |  |  | | | |
//            0 *1* 2 3 4 5
)

Так как же получить все комбинации?

Довольно просто я зацикливаюсь на каждом отдельном символе, который я хочу заменить на цикл foreach, а затем перебираю каждую отдельную комбинацию и объединяю ее с символом, который в настоящее время является значением цикла foreach.

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

Characters which have to be replaced (Empty array is '[]'): [1, 2, 3]

                               //new combinations for the next iteration
|
Character loop for NAN*:

Combinations:
- []         |  -> []

Character loop for 1:

Combinations:
- []    + 1  |  -> [1]

Character loop for 2:

Combinations:
- []    + 2  |  -> [2]
- [1]   + 2  |  -> [1,2]

Character loop for 3:

Combinations:
- []    + 3  |  -> [3]
- [1]   + 3  |  -> [1,3]
- [2]   + 3  |  -> [2,3]
- [1,2] + 3  |  -> [1,2,3]
//^ All combinations here

* NAN: не номер

Итак, как вы можете видеть, всегда есть: (2^n)-1 Всего комбинаций. Также от этого метода остается пустой массив в массиве комбинаций, поэтому, прежде чем я верну массив, я просто использую array_filter() удалить все пустые массивы и array_values() переиндексировать весь массив.

3. Запасная часть

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

array_intersect(str_split($str), array_keys($replace))

Это просто совпадение с array_intersect() из строки в виде массива с str_split() и ключи из массива замены с array_keys().

В этом коде массив, который вы передаете getReplacements() функция будет выглядеть примерно так:

Array
(
[1] => a
//^     ^ The single character which is in the string and also in the replace array
//| Index in the string from the character
[3] => e
[5] => i
)

4. Заменить все комбинации

В конце вам нужно только заменить все комбинации в исходной строке на массив замены. Для этого я перебираю все комбинации и заменяю каждый отдельный символ в строке на соответствующий символ из массива замены.

Это можно просто сделать с помощью этой строки:

$tmp = substr_replace($tmp, $replace[$v], $k, 1);
//^^^^^^^^^^^^^^       ^^^^^^^^^^^^  ^^  ^ Length of the replacement
//|                    |             | Index from the string, where it should replace
//|                    | Get the replaced character to replace it
//| Replaces every single character one by one in the string

Для получения дополнительной информации о substr_replace() см. руководство: http://php.net/manual/en/function.substr-replace.php

После этой строки вы просто добавляете замененную строку в массив результатов и снова помещаете строку в исходную строку.

Код:

<?php

//data
$str = "tazeki";

$replace = array(
'a' => 'ą',
'e' => 'ę',
'i' => 'į',
);function getReplacements($array) {

//initalize array
$results = [[]];

//get all combinations
foreach ($array as $k => $element) {
foreach ($results as $combination)
$results[] = [$k => $element] + $combination;
}

//return filtered array
return array_values(array_filter($results));

}

//get all combinations to replace
$combinations = getReplacements(array_intersect(str_split($str), array_keys($replace)));

//replace all combinations
foreach($combinations as $word) {
$tmp = $str;
foreach($word as $k => $v)
$tmp = substr_replace($tmp, $replace[$v], $k, 1);
$result[] = $tmp;
}

//print data
print_r($result);

?>

Выход:

Array
(
[0] => tązeki
[1] => tazęki
[2] => tązęki
[3] => tazekį
[4] => tązekį
[5] => tazękį
[6] => tązękį
)
5

Другие решения

Вот решение специально для вашей задачи. Вы можете передать любое слово и любой массив для замены, это должно работать.

<?php

function getCombinations($word, $charsReplace)
{
$charsToSplit = array_keys($charsReplace);

$pattern = '/('.implode('|', $charsToSplit).')/';

// split whole word into parts by replacing symbols
$parts = preg_split($pattern, $word, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);

$replaceParts = array();
$placeholder = '';

// create string with placeholders (%s) for sptrinf and array of replacing symbols
foreach ($parts as $wordPart) {
if (isset($charsReplace[$wordPart])) {
$replaceParts[] = $wordPart;
$placeholder .= '%s';
} else {
$placeholder .= $wordPart;
}
}

$paramsCnt = count($replaceParts);
$combinations = array();
$combinationsCnt = pow(2, $paramsCnt);

// iterate all combinations (with help of binary codes)
for ($i = 0; $i < $combinationsCnt; $i++) {
$mask = sprintf('%0'.$paramsCnt.'b', $i);
$sprintfParams = array($placeholder);
foreach ($replaceParts as $index => $char) {
$sprintfParams[] = $mask[$index] == 1 ? $charsReplace[$char] : $char;
}
// fill current combination into placeholder and collect it in array
$combinations[] = call_user_func_array('sprintf', $sprintfParams);
}

return $combinations;
}$lt = array(
'a' => 'ą',
'e' => 'ę',
'i' => 'į',
);
$word = 'stazeki';

$combinations = getCombinations($word, $lt);

print_r($combinations);

// Оutput:
// Array
// (
//     [0] => stazeki
//     [1] => stazekį
//     [2] => stazęki
//     [3] => stazękį
//     [4] => stązeki
//     [5] => stązekį
//     [6] => stązęki
//     [7] => stązękį
// )
2

Это реализация в PHP:

<?php
/**
* String variant generator
*/
class stringVariantGenerator
{
/**
* Contains assoc of char => array of all its variations
* @var array
*/
protected $_mapping = array();

/**
* Class constructor
*
* @param array $mapping Assoc array of char => array of all its variation
*/
public function __construct(array $mapping = array())
{
$this->_mapping = $mapping;
}

/**
* Generate all variations
*
* @param string $string String to generate variations from
*
* @return array Assoc containing variations
*/
public function generate($string)
{
return array_unique($this->parseString($string));
}

/**
* Parse a string and returns variations
*
* @param string $string String to parse
* @param int $position Current position analyzed in the string
* @param array $result Assoc containing all variations
*
* @return array Assoc containing variations
*/
protected function parseString($string, $position = 0, array &$result = array())
{
if ($position <= strlen($string) - 1)
{
if (isset($this->_mapping[$string{$position}]))
{
foreach ($this->_mapping[$string{$position}] as $translatedChar)
{
$string{$position} = $translatedChar;
$this->parseString($string, $position + 1, $result);
}
}
else
{
$this->parseString($string, $position + 1, $result);
}
}
else
{
$result[] = $string;
}

return $result;
}
}

// This is where you define what are the possible variations for each char
$mapping = array(
'e' => array('#', '_'),
'p' => array('*'),
);

$word = 'Apple love!';
$generator = new stringVariantGenerator($mapping);
print_r($generator->generate($word));

Это вернуло бы:

Array
(
[0] => A**l# lov#!
[1] => A**l# lov_!
[2] => A**l_ lov#!
[3] => A**l_ lov_!
)

В вашем случае, если вы хотите использовать само письмо в качестве допустимого переведенного значения, просто добавьте его в массив.

$lt = array(
'a' => array('a', 'ą'),
'e' => array('e', 'ę'),
'i' => array('i', 'į'),
);
1

Я не уверен, что вы можете сделать это с ключами и значением, но как два массива определенно.

$find = array('ą','ę','į');
$replace = array('a', 'e', 'i');
$string = 'tązekį';
echo str_replace($find, $replace, $string);
0

Я не уверен, что понимаю ваш вопрос, но вот мой ответ 🙂

$word = 'taxeki';
$word_arr = array();
$word_arr[] = $word;

//Loop through the $lt-array where $key represents what char to search for
//$letter what to replace with
//
foreach($lt as $key=>$letter) {

//Loop through each char in the $word-string
for( $i = 0; $i <= strlen($word)-1; $i++ ) {
$char = substr( $word, $i, 1 );

//If current letter in word is same as $key from $lt-array
//then add a word the $word_arr where letter is replace with
//$letter from the $lt-array
if ($char === $key) {
$word_arr[] = str_replace($char, $letter, $word);
}

}

}

var_dump($word_arr);
0

Я предполагаю, что у вас есть известное количество элементов в вашем массиве, и я предполагаю, что это число равно 3. У вас будут дополнительные циклы, если у вас есть дополнительные элементы в вашем массиве $ lt.

$lt = array(
'a' => array('a', 'x'),
'e' => array('e', 'x'),
'i' => array('i', 'x')
);
$str = 'tazeki';
foreach ($lt['a'] as $a)
foreach ($lt['e'] as $b)
foreach ($lt['i'] as $c) {
$newstr = str_replace(array_keys($lt), array($a, $b, $c), $str);
echo "$newstr<br />\n";
}

Если количество элементов в $lt неизвестно или переменная, то это не хорошее решение.

0

Что ж, хотя @ Rizier123 и другие уже предоставили хорошие ответы, дадут четкие объяснения, я также хотел бы оставить свой вклад. На этот раз, почитая Путь короткого исходного кода над читабельностью … 😉

$lt   = array('a' => 'ą', 'e' => 'ę', 'i' => 'į');
$word = 'tazeki';

for ($i = 0; $i < strlen($word); $i++)
$lt[$word[$i]] && $r[pow(2, $u++)] = [$lt[$word[$i]], $i];

for ($i = 1; $i < pow(2, count($r)); $i++) {
for ($w = $word, $u = end(array_keys($r)); $u > 0; $u >>= 1)
($i & $u) && $w = substr_replace($w, $r[$u][0], $r[$u][1], 1);
$res[] = $w;
}

print_r($res);

Выход:

Array
(
[0] => tązeki
[1] => tazęki
[2] => tązęki
[3] => tazekį
[4] => tązekį
[5] => tazękį
[6] => tązękį
)
0
По вопросам рекламы [email protected]