php 不带 strrev 的反向字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29817361/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reverse string without strrev
提问by prehfeldt
Some time ago during a job interview I got the task to reverse a string in PHP withoutusing strrev
.
前段时间在一次求职面试中,我得到了在 PHP 中反转字符串而不使用strrev
.
My first solution was something like this:
我的第一个解决方案是这样的:
$s = 'abcdefg';
$temp = '';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$temp .= $s{$length - $i - 1};
}
var_dump($temp);
// outputs string(7) "gfedcba"
then they asked me if I could do this without doubling the memory usage (not using the $temp
variable or any variable to copy the reversed string to) and I failed.
This kept bugging me and since then I tried to solve this multiple times but I constantly failed.
然后他们问我是否可以在不加倍内存使用量的情况下执行此操作(不使用$temp
变量或任何变量将反向字符串复制到),我失败了。这一直困扰着我,从那以后我多次尝试解决这个问题,但我总是失败。
My latest try looks like this:
我最近的尝试是这样的:
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$s = $s{$i * 2} . $s;
}
var_dump($s);
// outputs string(14) "gfedcbaabcdefg"
It's not a solution to chop off "abcdefg" after the loop because then I would still double the amount of memory used. I need to remove the last character in every iteration of the loop.
在循环之后切断“abcdefg”并不是一个解决方案,因为那样我仍然会将使用的内存量加倍。我需要在循环的每次迭代中删除最后一个字符。
I tried to use mb_substr
like this:
我试着这样使用mb_substr
:
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$s = $s{$i * 2} . mb_substr($s, $length - $i - 1, 1);
}
var_dump($s);
but it only gives me Uninitialized string offset
errors.
但它只会给我Uninitialized string offset
错误。
This is where I'm stuck (again). I tried googling but all the solutions I found either echo
the characters directly or use a temporary variable.
这是我(再次)卡住的地方。我尝试使用谷歌搜索,但我找到的所有解决方案要么echo
直接找到字符,要么使用临时变量。
I also found the Question PHP String reversal without using extra memorybut there's no answer that fits my needs.
我还发现了 Question PHP String reversal without using extra memory但没有适合我需要的答案。
回答by ksbg
That's an interesting one. Here's something I just came up with:
这是一个有趣的。这是我刚刚想出的东西:
$s = 'abcdefghijklm';
for($i=strlen($s)-1, $j=0; $j<$i; $i--, $j++) {
list($s[$j], $s[$i]) = array($s[$i], $s[$j]);
}
echo $s;
list()
can be used to assign a list of variables in one operation. So what I am doing is simply swapping characters (starting with first and last, then second-first and second-last and so on, till it reaches the middle of the string)
list()
可用于在一次操作中分配变量列表。所以我所做的只是交换字符(从第一个和最后一个开始,然后是第二个和第二个,依此类推,直到它到达字符串的中间)
Output is mlkjihgfedcba
.
Not using any other variables than $s
and the counters, so I hope that fits your criteria.
输出是mlkjihgfedcba
。不使用任何其他变量而不是$s
计数器,所以我希望它符合您的标准。
回答by ebo
You can use the fact that in PHP a string can be thought of as an array of characters.
您可以利用这样一个事实,即在 PHP 中可以将字符串视为字符数组。
Then basically what you want to do is to replace each character $i
on the left side of the middle of the string with the character $j
on the right side of the middle with the same distance.
那么基本上你想要做的就是用相同距离的中间右侧$i
的字符替换字符串中间左侧的每个字符$j
。
For example, in a string of seven characters the middle character is on position 3. The character on position 0 (distance 3) needs to be swapped with the character on position 6 (3 + 3), the character on position 1 (distance 2) needs to be swapped with the character on position 5 (3 + 2), etc.
例如,在一个由七个字符组成的字符串中,中间的字符位于位置 3。位置 0(距离 3)上的字符需要与位置 6(3 + 3)上的字符、位置 1(距离 2)上的字符交换) 需要与位置 5 (3 + 2) 上的字符交换,依此类推。
This algorithm can be implemented as follows:
该算法可以实现如下:
$s = 'abcdefg';
$length = strlen($s);
for ($i = 0, $j = $length-1; $i < ($length / 2); $i++, $j--) {
$t = $s[$i];
$s[$i] = $s[$j];
$s[$j] = $t;
}
var_dump($s);
回答by Bart?omiej Wach
$string = 'abc';
$reverted = implode(array_reverse(str_split($string)));
回答by Bushra Shahid
Try this:
尝试这个:
$s = 'abcdefg';
for ($i = strlen($s)-1; $i>=0; $i--) {
$s .= $s[$i];
$s[$i] = NULL;
}
var_dump(trim($s));
回答by Gerard
You could use the XOR swap trick.
您可以使用 XOR 交换技巧。
function rev($str) {
$len = strlen($str);
for($i = 0; $i < floor($len / 2); ++$i) {
$str[$i] = $str[$i] ^ $str[$len - $i - 1];
$str[$len - $i - 1] = $str[$i] ^ $str[$len - $i - 1];
$str[$i] = $str[$i] ^ $str[$len - $i - 1];
}
return $str;
}
print rev("example");
回答by George Garchagudashvili
Here it is PHP7 version of this:
这是它的 PHP7 版本:
echo "\u{202E}abcdefg"; // outs: gfedcba
回答by Christoph Burschka
PHP strings are kinda-sorta mutable, but due to copy-on-write it's very difficult to modify them in-place without a copy being made. Some of the above solutions work, but only because they're stand-alone; some already fail because they define a function without a pass-by-reference argument. To get the code to actually operate in-place in a larger program, you'd need to pay careful attention to assignments, function arguments, and scopes.
PHP 字符串有点可变,但由于写时复制,很难在不制作副本的情况下就地修改它们。上述一些解决方案有效,但仅仅是因为它们是独立的;有些已经失败了,因为他们定义了一个没有传递引用参数的函数。为了让代码在更大的程序中实际运行,您需要特别注意赋值、函数参数和作用域。
Example:
例子:
$string1 = 'abc';
$string2 = $string1;
$string1[0] = 'b';
print("$string1, $string2");
> "abc, bbc"
I suppose that if between initializing the variable and modifying it you only ever used by-reference assignments (&=
) and reference arguments (function rev(&$string)
) (or assign the string to an object property initially, and then never assign it to any other variable), you mightbe able to change the original value of the string without making any copies. That's a bit ridiculous, however, and I'd assume that the interviewer who came up with that question didn't know about copy-on-write.
我想,如果在初始化变量和修改它之间你只使用过引用赋值(&=
)和引用参数(function rev(&$string)
)(或最初将字符串分配给对象属性,然后再不将其分配给任何其他变量),你可能能够更改字符串的原始值而无需进行任何复制。然而,这有点荒谬,我认为提出这个问题的面试官不知道写时复制。
This isn't quite the same as immutability in other languages, by the way, because it applies to arrays too:
顺便说一下,这与其他语言中的不变性并不完全相同,因为它也适用于数组:
$a = [0, 1, 2];
$b = $a;
$b[0] = 1;
print(implode($a).implode($b));
> "012112"
To sum up, all types (exceptfor objects as of PHP5) are assigned with copy-on-write unless you specifically use the &=
operator. The assignment doesn't copy them, but unlike most other languages (C, Java, Python...) that either change the original value (arrays) or don't allow write access at all (strings), PHP will silently create a copy before making any changes.
总而言之,除非您专门使用运算符,否则所有类型(PHP5 中的对象除外)都被分配了写时复制&=
。赋值不会复制它们,但与大多数其他语言(C、Java、Python...)不同,它们要么更改原始值(数组),要么根本不允许写访问(字符串),PHP 将默默地创建一个在进行任何更改之前复制。
Of course, if you switched to a language with more conventional pointers and also switched to byte arrays instead of strings, you could use XOR to swap each pair of characters in place:
当然,如果您切换到具有更传统指针的语言并切换到字节数组而不是字符串,您可以使用 XOR 来交换每对字符:
for i = 0 ... string.length / 2:
string[i] ^= string[string.length-1-i]
string[string.length-1-i] ^= string[i]
string[i] ^= string[string.length-1-i]
回答by JPMC
Basically @EricBouwers answer, but you can remove the 2nd placeholder variable $j
基本上@EricBouwers 回答,但您可以删除第二个占位符变量 $j
function strrev2($str)
{
$len = strlen($str);
for($i=0;$i<$len/2;$i++)
{
$tmp = $str[$i];
$str[$i] = $str[$len-$i-1];
$str[$len-$i-1] = $tmp;
}
return $str;
}
Test for the output:
测试输出:
echo strrev2("Hi there!"); // "!ereht iH"
echo PHP_EOL;
echo strrev2("Hello World!"); // "!dlroW olleH"
This will go through the list and stop halfway, it swaps the leftmost and rightmost, and works it's way inward, and stops at the middle. If odd numbered, the pivot digit is never swapped with itself, and if even, it swaps the middle two and stops. The only extra memory used is $len
for convenience and $tmp
for swapping.
这将遍历列表并在中途停止,它交换最左侧和最右侧,并向内工作,并在中间停止。如果是奇数,则主元数字永远不会与自身交换,如果是偶数,则交换中间的两个并停止。唯一使用的额外内存是$len
为了方便和$tmp
交换。
If you want a function that doesn't return a new copy of the string, but just edits the old one in place you can use the following:
如果您想要一个不返回字符串的新副本,而只是在原地编辑旧副本的函数,您可以使用以下命令:
function strrev3(&$str)
{
$len = strlen($str);
for($i=0;$i<$len/2;$i++)
{
$tmp = $str[$i];
$str[$i] = $str[$len-$i-1];
$str[$len-$i-1] = $tmp;
}
}
$x = "Test String";
echo $x; // "Test String"
strrev3($x);
echo PHP_EOL;
echo $x; // "gnirtS tseT"
Using &$str
passes a direct pointer the the string for editing in place.
使用&$str
传递直接指针的字符串进行就地编辑。
And for a simpler implementation like @treegardens, you can rewrite as:
对于像@treegardens 这样更简单的实现,您可以重写为:
$s = 'abcdefghijklm';
$len = strlen($s);
for($i=0; $i < $len/2; $i++) {
list($s[$i], $s[$len-$i-1]) = array($s[$len-$i-1], $s[$i]);
}
echo $s;
It has the similar logic, but I simplified the for-loop quite a bit.
它有类似的逻辑,但我大大简化了 for 循环。
回答by JPMC
Its Too Simple
它太简单了
//Reverse a String
$string = 'Basant Kumar';
$length = strlen($string);
for($i=$length-1;$i >=0;$i--){
echo $string[$i];
}
回答by Islam Zedan
Here is my code to solve your problem
这是我的代码来解决您的问题
<?php
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
$s = $s{$i}.mb_substr($s,0,$i).mb_substr($s,$i+1);
}
var_dump($s);
?>