如何检查两个字符串的开头是否相同?

时间:2019-09-30 21:14:47

标签: php string

考虑到我有一维有序的字符串数组:

$arr = [
    'Something else',
    'This is option: one',
    'This is option: two',
    'This is option: ?',
    'This is second option: 2',
    'This is second option: 3'
];

我想将其转换为二维数组,并以共同的开头作为关键。例如:

$target = [
    'Something else',
    'This is option:' => [
        'one',
        'two',
        '?'
    ],
    'This is second option:' => [
        '2',
        '3'
    ]
];

这听起来很简单,但是我完全空白了。

function convertArr(array $src): array {
    $prevString = null;
    $newArray = [];
    foreach ($src as $string) {
        if ($prevString) {
            // stuck here
        }
        $prevString = $string;
    }
    return $newArray;
}

预制小提琴:https://3v4l.org/eqGDc

如何检查两个字符串是否以相同的词开头,而不必在每个字母上循环?

到目前为止,我已经编写了这个过于复杂的函数,但是我想知道是否有更简单的方法:

function convertArr(array $src): array {
    $prevString = null;
    $newArray = [];

    $size = count($src);
    for ($i = 0; $i < $size; $i++) {
        if (!$prevString || strpos($src[$i], $prevString) !== 0) {
            if ($i == $size - 1) {
                $newArray[] = $src[$i];
                break;
            }
            $nowWords = explode(' ', $src[$i]);
            $nextWords = explode(' ', $src[$i + 1]);
            foreach ($nowWords as $k => $v) {
                if ($v != $nextWords[$k]) {
                    break;
                }
            }
            if ($k) {
                $prevString = implode(' ', array_splice($nowWords, 0, $k));
                $newArray[$prevString][] = implode(' ', $nowWords);
            }
        } else {
            $newArray[$prevString][] = trim(substr($src[$i], strlen($prevString)));
        }
    }
    return $newArray;
}

2 个答案:

答案 0 :(得分:1)

我还没有一个完整的解决方案,但是也许您可以以此为起点:以下内容为您提供了长度为2的数组中字符串的最长的通用起始序列:

var s=["This is option: one","This is option: two"]; 
var same=s.join('|').match(/(.*)(.*?)\|\1.*/)[1];
// same="This is option: "

same中,您将在数组s中找到两个字符串中最长的开头。我通过使用带有贪婪和非贪婪通配符组的正则表达式并强制第一个组重复来实现此目的。

您可以在原始排序的输入数组的slice()-d个短数组上应用此方法,并监视same对于这些子数组中的多个数组是否保持相同。然后,您可以对具有相同same的部分执行预期的分组操作。

[[抱歉,我刚刚意识到我用JavaScript编写了此代码,而您需要PHP-但想法很简单,您可以自己将其轻松转换为PHP。 ]]

修改

在我再次查看问题和预期结果时,OP真正希望的是将冒号(:)之前具有相似部分的元素组合到一个公共子数组中。可以使用以下代码完成此操作:

$arr = [
    'Is there anything new and',
    'Something old',
    'This is option: one',
    'This is option: two',
    'This is option: ?',
    'This is second option: 2',
    'This is second option: 3',
    'Abc: def',
    'Abc: ghi',
    'the same line',
    'the same words'
];
foreach($arr as $v) {
 $t=array_reverse(explode(':',$v));
 $target[isset($t[1])?trim($t[1]):0][]=trim($t[0]);
}
print_r($target)

输出:

Array
(
    [0] => Array
        (
            [0] => Is there anything new and
            [1] => Something old
            [2] => the same line
            [3] => the same words
        )

    [This is option] => Array
        (
            [0] => one
            [1] => two
            [2] => ?
        )

    [This is second option] => Array
        (
            [0] => 2
            [1] => 3
        )

    [Abc] => Array
        (
            [0] => def
            [1] => ghi
        )

)

https://rextester.com/JMB6676上查看演示

答案 1 :(得分:1)

这可以完成工作:

function convertArray(array $values): array
{
    $newArray = [];
    foreach ($values as $value) {
        if (stripos($value, ':') !== false) {
            $key = strtok($value, ':');
            $newArray[$key][] = trim(substr($value, stripos($value, ':') + 1));
        }
    }

    return $newArray;
}

基本上,根据您的字符串数组的格式,只要每个字符串只有一个“:”字符后跟选项值,这应该就足够了。

我肯定会有一个更高级,更故障保护的解决方案,但这可能是一个开始。