反转可能包含多字节字符的字符串的每个单词中所有字母的位置
Reverse the position of all letters in each word of a string that may contain multibyte characters
我想编写一个应用程序来反转输入文本的所有单词,但所有非字母符号都应保留在相同的位置。
我已经拥有的:
function reverse($string)
{
$reversedString = '';
for ($position = strlen($string); $position > 0; $position--) {
$reversedString .= $string[$position - 1]; //.= - concatenation assignment, привязывает b to a;
}
return $reversedString;
}
$name = 'ab1 ab2';
print_r(reverse($name)); //output: 2ba 1ba;
现在我想为这个函数添加一些结论,这个函数也将反转文本,但不影响任何特殊字符?这意味着,所有非字母符号都应位于相同的位置。
下面是一些示例输入字符串和我想要的输出:
ab1 ab2
变为 ba1 ba2
qwerty uiop
变为 ytrewq poiu
q1werty% uio*pl
变为 y1trewq% lpo*iu
Привет, мир!
变为 тевирП, рим!
Hello, dear @user_non-name, congrats100 points*@!
变为 olleH, raed @eman_non-resu, stragnoc100 stniop*@!
我的实际项目将使用西里尔字符,因此答案需要包含 multibyte/unicode 个字母。
也许我应该使用数组和“'ctype_alpha'”函数?
如果我对您的问题的理解正确,那么下面的解决方案可能会对您有所帮助。此解决方案不简洁且不是最优的,但它似乎有效:
//mb_internal_encoding('UTF-8') && mb_regex_encoding('UTF-8'); // <-- if you need
function reverse(string $string): string
{
$reversedStrings = explode(' ', $string);
$patternRegexp = '^[a-zA-Zа-яА-Я]+$';
foreach ($reversedStrings as &$word) {
$chars = mb_str_split($word, 1);
$filteredChars = [];
foreach (array_reverse($chars) as $char) {
if (mb_ereg_match($patternRegexp, $char)) {
$filteredChars[] = $char;
}
}
foreach ($chars as &$char) {
if (!mb_ereg_match($patternRegexp, $char)) {
continue;
}
$char = array_shift($filteredChars);
}
$word = implode('', $chars);
}
return implode(' ', $reversedStrings);
}
$test1 = 'ab1 ab2 ab! ab. Hello!789World! qwe4rty5';
print_r(reverse($test1)."\n"); // => "ba1 ba2 ba! ba. dlroW!789olleH! ytr4ewq5";
$test2 = 'Привет, мир!';
print_r(reverse($test2)."\n"); // => "тевирП, рим!";
在示例中,非字母字符不会改变它们在单词中的位置。示例:“Hello!789World!qwe4rty5”=>“dlroW!789olleH!ytr4ewq5”。
为了通过减少函数调用总数和 preg_
调用次数来优化性能,我将演示一种嵌套循环技术。
- 在空格处爆炸
- 在容纳多字节字符的同时将字母与非字母分开
- 迭代每行包含 1 个字符的匹配数组(分隔以便字母(可移动字符)位于
[1]
元素中,非字母(不可移动字符位于 [2]
元素中。
- 在字符数组从左到右遍历时,如果遇到不能移动的字符,立即追加到当前输出字符串;如果是可移动的,则从匹配数组的末尾寻找最新未使用的可移动字符。
代码:(Demo) (variation without isset() calls)
$names = [
'ab1 ab2', // becomes ba1 ba2
'qwerty uçop', // becomes ytrewq poçu
'q1werty% uio*pl', // becomes y1trewq% lpo*iu
'Привет, мир!', // becomes тевирП, рим!
'Hello, dear @user_non-name, congrats100 points*@!', // olleH, raed @eman_non-resu, stragnoc100 stniop*@!
'a' // remains a
];
function swapLetterPositions($string): string {
$result = [];
foreach (explode(' ', $string) as $index => $word) {
$result[$index] = '';
$count = preg_match_all('/(\pL)|(.)/u', $word, $m, PREG_SET_ORDER);
for ($i = 0, $j = $count; $i < $count; ++$i) {
if (isset($m[$i][2])) { // immovable
$result[$index] .= $m[$i][2]; // append to string
} else { // movable from front
while (--$j >= 0) { // decrement $j and ensure that it represents an element index
if (!isset($m[$j][2])) { // movable from back
$result[$index] .= $m[$j][1]; // append to string
break;
}
}
}
}
}
return implode(' ', $result);
}
foreach ($names as $name) {
echo "\"$name\" => \"" . swapLetterPositions($name) . "\"\n---\n";
}
输出:
"ab1 ab2" => "ba1 ba2"
---
"qwerty uçop" => "ytrewq poçu"
---
"q1werty% uio*pl" => "y1trewq% lpo*iu"
---
"Привет, мир!" => "тевирП, рим!"
---
"Hello, dear @user_non-name, congrats100 points*@!" => "olleH, raed @eman_non-resu, stargnoc100 stniop*@!"
---
"a" => "a"
---
我想编写一个应用程序来反转输入文本的所有单词,但所有非字母符号都应保留在相同的位置。
我已经拥有的:
function reverse($string)
{
$reversedString = '';
for ($position = strlen($string); $position > 0; $position--) {
$reversedString .= $string[$position - 1]; //.= - concatenation assignment, привязывает b to a;
}
return $reversedString;
}
$name = 'ab1 ab2';
print_r(reverse($name)); //output: 2ba 1ba;
现在我想为这个函数添加一些结论,这个函数也将反转文本,但不影响任何特殊字符?这意味着,所有非字母符号都应位于相同的位置。
下面是一些示例输入字符串和我想要的输出:
ab1 ab2
变为ba1 ba2
qwerty uiop
变为ytrewq poiu
q1werty% uio*pl
变为y1trewq% lpo*iu
Привет, мир!
变为тевирП, рим!
Hello, dear @user_non-name, congrats100 points*@!
变为olleH, raed @eman_non-resu, stragnoc100 stniop*@!
我的实际项目将使用西里尔字符,因此答案需要包含 multibyte/unicode 个字母。
也许我应该使用数组和“'ctype_alpha'”函数?
如果我对您的问题的理解正确,那么下面的解决方案可能会对您有所帮助。此解决方案不简洁且不是最优的,但它似乎有效:
//mb_internal_encoding('UTF-8') && mb_regex_encoding('UTF-8'); // <-- if you need
function reverse(string $string): string
{
$reversedStrings = explode(' ', $string);
$patternRegexp = '^[a-zA-Zа-яА-Я]+$';
foreach ($reversedStrings as &$word) {
$chars = mb_str_split($word, 1);
$filteredChars = [];
foreach (array_reverse($chars) as $char) {
if (mb_ereg_match($patternRegexp, $char)) {
$filteredChars[] = $char;
}
}
foreach ($chars as &$char) {
if (!mb_ereg_match($patternRegexp, $char)) {
continue;
}
$char = array_shift($filteredChars);
}
$word = implode('', $chars);
}
return implode(' ', $reversedStrings);
}
$test1 = 'ab1 ab2 ab! ab. Hello!789World! qwe4rty5';
print_r(reverse($test1)."\n"); // => "ba1 ba2 ba! ba. dlroW!789olleH! ytr4ewq5";
$test2 = 'Привет, мир!';
print_r(reverse($test2)."\n"); // => "тевирП, рим!";
在示例中,非字母字符不会改变它们在单词中的位置。示例:“Hello!789World!qwe4rty5”=>“dlroW!789olleH!ytr4ewq5”。
为了通过减少函数调用总数和 preg_
调用次数来优化性能,我将演示一种嵌套循环技术。
- 在空格处爆炸
- 在容纳多字节字符的同时将字母与非字母分开
- 迭代每行包含 1 个字符的匹配数组(分隔以便字母(可移动字符)位于
[1]
元素中,非字母(不可移动字符位于[2]
元素中。 - 在字符数组从左到右遍历时,如果遇到不能移动的字符,立即追加到当前输出字符串;如果是可移动的,则从匹配数组的末尾寻找最新未使用的可移动字符。
代码:(Demo) (variation without isset() calls)
$names = [
'ab1 ab2', // becomes ba1 ba2
'qwerty uçop', // becomes ytrewq poçu
'q1werty% uio*pl', // becomes y1trewq% lpo*iu
'Привет, мир!', // becomes тевирП, рим!
'Hello, dear @user_non-name, congrats100 points*@!', // olleH, raed @eman_non-resu, stragnoc100 stniop*@!
'a' // remains a
];
function swapLetterPositions($string): string {
$result = [];
foreach (explode(' ', $string) as $index => $word) {
$result[$index] = '';
$count = preg_match_all('/(\pL)|(.)/u', $word, $m, PREG_SET_ORDER);
for ($i = 0, $j = $count; $i < $count; ++$i) {
if (isset($m[$i][2])) { // immovable
$result[$index] .= $m[$i][2]; // append to string
} else { // movable from front
while (--$j >= 0) { // decrement $j and ensure that it represents an element index
if (!isset($m[$j][2])) { // movable from back
$result[$index] .= $m[$j][1]; // append to string
break;
}
}
}
}
}
return implode(' ', $result);
}
foreach ($names as $name) {
echo "\"$name\" => \"" . swapLetterPositions($name) . "\"\n---\n";
}
输出:
"ab1 ab2" => "ba1 ba2"
---
"qwerty uçop" => "ytrewq poçu"
---
"q1werty% uio*pl" => "y1trewq% lpo*iu"
---
"Привет, мир!" => "тевирП, рим!"
---
"Hello, dear @user_non-name, congrats100 points*@!" => "olleH, raed @eman_non-resu, stargnoc100 stniop*@!"
---
"a" => "a"
---