将一个字符串中的一般模式匹配到另一个

时间:2019-11-26 22:21:22

标签: php

我有一个以这种格式存储在数组中的扑克手列表:

$hands = ['AsQdTc9h', 'AsQsTd9d' ...]

我还有一个4个字符的搜索字符串,并使用字母xyzw。例如,搜索字符串可能类似于:

$searchString = 'xyxy';
$searchString = 'xyzw';
$searchString = 'yzyw';

搜索字符串的全部目的是为手中的小写字母标识所需的模式。

因此,如果searchString为xyzw,那只是说“只选择没有小写字母相等的手”的一种方式。如果搜索字符串为xyxy,那是一种“只选择第一个和第三个小写字母相等而第二个和第四个小写字母相等的手。

换句话说,小写字母必须与搜索字符串的模式匹配。如何在PHP中实现呢?

3 个答案:

答案 0 :(得分:0)

$MyString = 'AsQdTc9h';
$MyString = preg_replace('/[^a-z]/', '', $MyString); // Get only the lowercase characters
// $MyString : sdch

$LetterArray = str_split($MyString);
$LetterArray = array_count_values($LetterArray);

$ReplaceList = ['x', 'y', 'z', 'w'];
$i = 0;
foreach ($LetterArray as $Letter => $result) {
    $MyString = str_replace($Letter, $ReplaceList[$i], $MyString);
    $i++;
}
echo $MyString; // expected output : xyzw

我想解释一下代码,以便您理解它,首先,我们使用正则表达式获取所有小写字符。然后我们将4个字符的单词转换为数组,然后计算出多少个字符相同。

然后将结果替换为xyzw。

答案 1 :(得分:0)

尽管这似乎是一个模式匹配任务,但是由于字符串的长度非常有限,伪暴力检查可能是最简单的。

function pokerMatch(string $hand, string $pattern): bool
{
    $hand = preg_replace('/[^a-z]/', '', $hand);

    for ($i = 0; $i < strlen($hand); $i++) {
        for ($j = $i+1; $j < strlen($hand); $j++) {
            if ($pattern[$i] === $pattern[$j] && $hand[$i] !== $hand[$j]) {
                return false;
            }
            if ($pattern[$i] !== $pattern[$j] && $hand[$i] === $hand[$j]) {
                return false;
            }
        }
    }
    return true;
}

这基本上是什么,它将遍历模式字符串,获取每对字符并进行检查:

  • 如果模式位置i和j中的字母相等,那么手串中的字符也必须相同;

  • 如果模式位置i和j中的字母不同,那么手串中的字符也必须相同;

如果其中任何一个不成立-模式不匹配

如果在检查所有对之后发现没有不匹配的地方,那就是匹配的地方。

用法:

var_dump(pokerMatch('AsQdTc9h', 'xyzw')); // => bool(true)
var_dump(pokerMatch('AsQdTc9h', 'xyzz')); // => bool(false)
var_dump(pokerMatch('AsQsTc9c', 'xxyy')); // => bool(true)
var_dump(pokerMatch('AsQsTc9c', 'zzww')); // => bool(true) (it's agnostic to exact letters)

答案 2 :(得分:0)

您可以通过以下方法解决此问题:遍历每只手和搜索字符串,记录哪个西装与哪个搜索字母匹配,并检查它们始终保持一致:

$hands = ['AsQdTc9h', 'AsQsTd9d', 'AsKh9s9d'];
$searchStrings = ['xyxy', 'xyzw', 'yzyw', 'ppqq'];

function match_hand($hand, $search) {
    $h = preg_replace('/[^a-z]/', '', $hand);
    $matches = array();
    for ($i = 0; $i < strlen($search); $i++) {
        $s = $search[$i];
        // have we seen this search letter before? 
        if (isset($matches[$s])) {
            // does it match the previous value? if not, it's an error
            if ($matches[$s] != $h[$i]) return false;
        }
        else {
            // haven't seen this search letter before, so this hand letter should not be in the matches array yet
            if (in_array($h[$i], $matches)) return false;
        }
        $matches[$s] = $h[$i];
    }
    return true;
}

foreach ($hands as $hand) {
    foreach ($searchStrings as $search) {
        if (match_hand($hand, $search)) {
            echo "hand $hand matches pattern $search\n";
        }
    }
}

输出:

hand AsQdTc9h matches pattern xyzw
hand AsQsTd9d matches pattern ppqq
hand AsKh9s9d matches pattern yzyw

Demo on 3v4l.org