在倒数第二个和最后一个 space 分解字符串以创建恰好 3 个元素
Explode string on second last and last space to create exactly 3 elements
我想用 space 分割一个 space 分隔的字符串,但我需要结果数组中的元素总数正好是 3 并且如果字符串有两个以上 spaces,只有最后两个 spaces 应该用作分隔符。
我的输入字符串遵循可预测的格式。字符串是一个或多个单词,然后是一个单词,然后是一个用括号括起来的单词(在此上下文中的单词是一个没有白色 space 的子字符串)。
示例字符串:
Stack Over Flow Abcpqr (UR)
变为:
["Stack Over Flow", "Abcpqr", "(UR)"]
Fluency in English Conversation Defklmno (1WIR)
变为:
["Fluency in English Conversation","Defklmno","(1WIR)"]
English Proficiency GHI (2WIR)
变为:
["English Proficiency","GHI","(2WIR)"]
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 个元素。
您可以使用 explode
和 str_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))));
}
我不喜欢正则表达式,但这个似乎工作得很好:
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。
我想用 space 分割一个 space 分隔的字符串,但我需要结果数组中的元素总数正好是 3 并且如果字符串有两个以上 spaces,只有最后两个 spaces 应该用作分隔符。
我的输入字符串遵循可预测的格式。字符串是一个或多个单词,然后是一个单词,然后是一个用括号括起来的单词(在此上下文中的单词是一个没有白色 space 的子字符串)。
示例字符串:
Stack Over Flow Abcpqr (UR)
变为:["Stack Over Flow", "Abcpqr", "(UR)"]
Fluency in English Conversation Defklmno (1WIR)
变为:["Fluency in English Conversation","Defklmno","(1WIR)"]
English Proficiency GHI (2WIR)
变为:["English Proficiency","GHI","(2WIR)"]
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 个元素。
您可以使用 explode
和 str_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))));
}
我不喜欢正则表达式,但这个似乎工作得很好:
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。