PHP替换符号所有可能的变体

时间:2015-02-28 16:57:34

标签: php replace combinations

我有我想要替换的数组符号,但我需要生成所有可能性

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

例如,如果我有这个字符串:

tazeki

可能会有大量的结果:

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

我的问题是什么配方用于拥有所有变种?

7 个答案:

答案 0 :(得分:5)

这应该对你有用,简单易行:

这段代码有什么作用?

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。替换所有组合

最后,您只需要用replace数组替换源字符串中的所有组合。为此,我循环遍历每个组合,并用替换数组中匹配字符的组合替换字符串中的每个字符。

这可以通过以下方式完成:

$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į
)

答案 1 :(得分:2)

这是一个特别适合您的任务的解决方案。你可以传递任何单词和任何数组进行替换,它应该可以工作。

<?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 :(得分:1)

这是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', 'į'),
);

答案 3 :(得分:0)

我不确定你是否可以使用键和值来做到这一点,但是作为两个数组definatley。

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

答案 4 :(得分: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);

答案 5 :(得分: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中的元素数量未知或可变,那么这不是一个好的解决方案。

答案 6 :(得分: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į
)