如何获取一个单词中所有可互换字母的可能变体?

8

在阿拉伯语中,像“ا”(Alef)这样的字母有许多形式/变化:

(ا,أ,إ,آ)

同样的情况也适用于字母ي,它也可以是ى。

我想做的是获取具有多个أ和ي字母的单词的所有可能的变体。

例如,“أين”这个单词应该有所有这些可能的(在大多数情况下不正确的)变体:أين,إين,اين,آين,أىن,إين,اىن,آىن等。

为什么?我正在构建一个小型文本校正系统,可以处理语法错误并将有误的单词替换为正确的单词。

我一直试图以最干净的方式来实现这一点,但最终我得到了8个for / foreach循环,只是为了处理单词“أ”

肯定有更好、更干净的方法来做到这一点!有什么想法吗?

以下是我到目前为止的代码:

        $alefVariations = ['ا', 'إ', 'أ', 'آ'];
        $word = 'أيامنا';

        // Break into letters
        $wordLetters = preg_split('//u', $word, null, PREG_SPLIT_NO_EMPTY);
        $wordAlefLettersIndexes = [];

        // Get the أ letters
        for($letterIndex = 0; $letterIndex < count($wordLetters); $letterIndex++){
            if(in_array($wordLetters[$letterIndex], $alefVariations)){
                $wordAlefLettersIndexes[] = $letterIndex;
            }
        }

        $eachLetterVariations = [];
        foreach($wordAlefLettersIndexes as $alefLettersIndex){
            foreach($alefVariations as $alefVariation){
                $wordCopy = $wordLetters;
                $wordCopy[$alefLettersIndex] = $alefVariation;

                $eachLetterVariations[$alefLettersIndex][] = $wordCopy;
            }
        }

        $variations = [];
        foreach($wordAlefLettersIndexes as $alefLettersIndex){
            $alefWordVariations = $eachLetterVariations[$alefLettersIndex];

            foreach($wordAlefLettersIndexes as $alefLettersIndex_inner){
                if($alefLettersIndex == $alefLettersIndex_inner) continue;

                foreach($alefWordVariations as $alefWordVariation){
                    foreach($alefVariations as $alefVariation){
                        $alefWordVariationCopy = $alefWordVariation;
                        $alefWordVariationCopy[$alefLettersIndex_inner] = $alefVariation;

                        $variations[] = $alefWordVariationCopy;
                    }
                }
            }
        }

        $finalList = [];
        foreach($variations as $variation){
            $finalList[] = implode('', $variation);
        }

        return array_unique($finalList);

2
你所说的可能最好通过机器学习/人工智能实现。 - Joseph_J
@Joseph_J 真的吗?这么复杂吗?我希望有一位大师能够给我一个10行代码的解决方案或者类似的东西 :) - Dewan159
首先将输入减少到基本字符,然后通过递归替换简化的单词来构建结果数组,以生成所有可能性,这样做是否可行?基本字符可以是替换矩阵的关键。 - Teson
1
我认为你自己已经回答了这个问题,一个简单的单词需要循环8次。我理解你的问题是在寻找一个预测文本应用程序。编写语言是很困难的,即使全世界最好的程序员也在不断完善它。 - Joseph_J
@Teson,如果我理解正确,我认为这种方法行不通。 - Dewan159
你能否去掉你的 OP 中字母周围的引号,因为这使它们难以阅读。我可以做到,但似乎会影响字母本身。 - Script47
1个回答

2

我认为这不是自动纠正的正确方法,但以下是一个解决你提出问题的通用方案。它使用递归,且是用JavaScript编写的(我不知道PHP)。

function solve(word, sameLetters, customIndices = []){
    var splitLetters = word.split('')
                .map((char, index) => { // check if the current letter is within any variation
                    if(customIndices.length == 0 || customIndices.includes(index)){
                        var variations = sameLetters.find(arr => arr.includes(char));
                        if(variations != undefined) return variations;
                    }
                    return [char];
                 });

    // up to this point splitLetters will be like this
    //  [["ا","إ","أ","آ"],["ي","ى","ي"],["ا"],["م"],["ن"],["ا"]]
    var res = [];
    recurse(splitLetters, 0, '', res); // this function will generate all the permuations
    return res;
}

function recurse(letters, index, cur, res){
    if(index == letters.length){
        res.push(cur);
    } else {
        for(var letter of letters[index]) {
            recurse(letters, index + 1, cur + letter, res );
        }
    }
}

var sameLetters = [     // represents the variations that you want to enumerate
    ['ا', 'إ', 'أ', 'آ'],
    ['ي', 'ى', 'ي']
];

var word = 'أيامنا';    
var customIndices = [0, 1]; // will make variations to the letters in these indices only. leave it empty for all indices

var ans = solve(word, sameLetters, customIndices);
console.log(ans);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接