在倒数第二个和最后一个 space 分解字符串以创建恰好 3 个元素

Explode string on second last and last space to create exactly 3 elements

我想用 space 分割一个 space 分隔的字符串,但我需要结果数组中的元素总数正好是 3 并且如果字符串有两个以上 spaces,只有最后两个 spaces 应该用作分隔符。

我的输入字符串遵循可预测的格式。字符串是一个或多个单词,然后是一个单词,然后是一个用括号括起来的单词(在此上下文中的单词是一个没有白色 space 的子字符串)。

示例字符串:

  1. Stack Over Flow Abcpqr (UR)
    变为:
    ["Stack Over Flow", "Abcpqr", "(UR)"]
  2. Fluency in English Conversation Defklmno (1WIR)
    变为:
    ["Fluency in English Conversation","Defklmno","(1WIR)"]
  3. English Proficiency GHI (2WIR)
    变为:
    ["English Proficiency","GHI","(2WIR)"]
  4. Testing ADG (3WIR)
    变为:
    ["Testing","ADG","(3WIR)"]

我使用了以下代码,但它只适用于 Testing (3WIR)

$Original = $row['fld_example'];                                    
$OriginalExplode = explode(' ', $Original);

<input name="example0" id="example0" value="<?php echo $OriginalExplode[0]; ?>" type="text" autocomplete="off" required>

<input name="example1" id="example1" value="<?php echo $OriginalExplode[1]; ?>" type="text" autocomplete="off" required>

基本上,我只需要在 spaces 上分解字符串,从字符串的末尾开始,并将总分解限制为 2(生成 3 个元素。

您可以使用 explodestr_replace

来解决这个问题
$string = "Testing (3WIR)";
$stringToArray = explode(":",str_replace("(",":(",$string));
echo '<pre>';
print_r($stringToArray);

编辑后的问题答案:-

$subject = "Fluency in English Conversation Defklmno (1WIR)";
$toArray = explode(' ',$subject);
if(count($toArray) > 2){
  $first       = implode(" ",array_slice($toArray, 0,count($toArray)-2));
  $second      = $toArray[count($toArray)-2];
  $third       = $toArray[count($toArray)-1];
  $result      = array_values(array_filter([$first, $second, $third]));
}else{
  $result = array_values(array_filter(explode(":",str_replace("(",":(",$subject))));
}

DEMO HERE

我不喜欢正则表达式,但这个似乎工作得很好:

Regex to split a string only by the last whitespace character

所以 PHP 代码将是:

function splitAtLastWord($sentence)
{
    return preg_split("/\s+(?=\S*+$)/", $sentence);
}

$sentence = "Fluency in English Conversation Defklmno (1WIR)";  

list($begin, $end)    = splitAtLastWord($sentence);
list($first, $middle) = splitAtLastWord($begin);
$result = [$first, $middle, $end]; 

echo "<pre>" . print_r($result, TRUE) . "</pre>";

输出为:

Array
(
    [0] => Fluency in English Conversation
    [1] => Defklmno
    [2] => (1WIR)
)

您也可以不使用正则表达式来编写相同的函数:

function splitAtLastWord($sentence)
{
    $words = explode(" ", $sentence);
    $last  = array_pop($words);
    return [implode(" ", $words), $last];
}

老实说,这是一种更好的方法。

这是一种计算效率更高的方法:

function splitAtLastWord($sentence)
{
   $lastSpacePos = strrpos($sentence, " ");
   return [substr($sentence, 0, $lastSpacePos), substr($sentence, $lastSpacePos + 1)]; 
}

它看起来不太好但速度更快。

无论如何,像这样定义一个单独的函数很有用,你可以在其他地方重用它。

要隔离两个定界 space,请使用 / (?=(?:\S+ )?\()/,它利用包含可选组的前瞻性。

代码:(Demo)

$strings = [
    'Stack Over Flow Abcpqr (UR)',
    'Fluency in English Conversation Defklmno (1WIR)',
    'English Proficiency GHI (2WIR)',
    'Testing ADG (3WIR)',
];

foreach ($strings as $string) {
    echo json_encode(
             preg_split('/ (?=(?:\S+ )?\()/', $string)
         ) . "\n";
}

输出:

["Stack Over Flow","Abcpqr","(UR)"]
["Fluency in English Conversation","Defklmno","(1WIR)"]
["English Proficiency","GHI","(2WIR)"]
["Testing","ADG","(3WIR)"]

模式分解:

             #match a literal space
(?=          #start lookahead
  (?:\S+ )?  #optionally match one or more non-whitespaces followed by a space
  \(         #match a literal opening parenthesis 
)            #end lookahead

匹配第一个分隔符space时,可选的子模式将匹配字符。当匹配第二个分隔符 space(括号前)时,可选子模式将不匹配任何字符。


作为一个更通用的解决方案,如果目标是在最后两个 non-whitespace 子串中的任何一个之前的 space 处拆分,则此模式以相同的方式向前看,但一直匹配到字符串的末尾。

/ (?=(?:\S+ )?\S+$)/

虽然我没有发现 non-regex 解决方案接近优雅或简洁,但这里有一种方法可以爆炸所有 spaced 然后内爆除最后两个元素之外的所有元素:( Demo)

function implodeNotLastTwoElements($string) {
    $array = explode(' ', $string);
    array_splice($array, 0, -2, implode(' ', array_slice($array, 0, -2)));
    return $array;
}

foreach ($strings as $string) {
    echo json_encode(implodeNotLastTwoElements($string)) . "\n";
}

或(Demo)

function implodeNotLastTwoElements($string) {
    $array = explode(' ', $string);
    return [implode(' ', array_slice($array, 0, -2))] + array_slice($array, -3);
}

这些 non-regex 方法是 iterating/scanning 遍历数据 4 次,而正则表达式仅扫描一次输入字符串并直接创建所需结果。在这种情况下,正则表达式或 non-regex 之间的决定对我来说是 no-brainer。