Ruby:1.9 中字符串不再混合在 Enumerable 中
那么我怎样才能仍然能够编写漂亮的代码,例如:
'im a string meing!'.pop
注意: str.chop
不是足够的答案
So how can I still be able to write beautiful code such as:
'im a string meing!'.pop
Note: str.chop
isn't sufficient answer
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
它不是可枚举字符串实际枚举的内容。字符串是……
答案是:所有这些、其中任何一个、其中之一或两者都不是,具体取决于上下文。因此,您必须告诉 Ruby 您真正想要哪一个。
String
类中有多种方法可以返回上述任何一个的枚举器。如果您想要 1.9 之前的行为,您的代码示例将是这看起来有点难看,但这是有原因的:字符串是一个序列。您将其视为堆栈。堆栈不是序列,事实上它几乎是序列的反面。
It is not what an enumerable string atually enumerates. Is a string a sequence of ...
The answer is: all of those, any of those, either of those or neither of those, depending on the context. Therefore, you have to tell Ruby which of those you actually want.
There are several methods in the
String
class which return enumerators for any of the above. If you want the pre-1.9 behavior, your code sample would beThis looks kind of ugly, but there is a reason for it: a string is a sequence. You are treating it as a stack. A stack is not a sequence, in fact it pretty much is the opposite of a sequence.
这不太漂亮:)
另外 #pop 不是 Enumerable 的一部分,它是 Array 的一部分。
String 不可枚举的原因是因为没有“自然”单位可供枚举,应该以字符为基础还是以行为基础?因为这个字符串没有 #each
字符串,而是提供了 #each_char 和 #each_byte 和 #each_line 方法,以您选择的方式进行迭代。
That's not beautiful :)
Also #pop is not part of Enumerable, it's part of Array.
The reason why String is not enumerable is because there are no 'natural' units to enumerate, should it be on a character basis or a line basis? Because of this String does not have an #each
String instead provides the #each_char and #each_byte and #each_line methods for iteration in the way that you choose.
既然你不喜欢 str[str.length],那么
or
or 怎么样,如果你还需要对其进行适当的修改,同时保持它是一个简单的单行:
Since you don't like str[str.length], how about
or
or, if you need it modified in place as well, while keeping it an easy one-liner:
String.rpartition 是 1.9 中的新增内容,但已向后移植到 1.8.7。它从字符串末尾开始向后搜索正则表达式。它返回匹配之前的字符串部分、匹配的部分以及匹配之后的字符串部分(我们在这里将其丢弃)。
String.rpartition is new for 1.9 but it's been back-ported to 1.8.7. It searches a string for a regular expression, starting at the end and working backwards. It returns the part of the string before the match, the match, and the part of the string after the match (which we discard here).
String#slice!
和String#insert
将使您更接近您想要的内容,而无需将字符串转换为数组。例如,要模拟
Array#pop
,您可以执行以下操作:同样,对于
Array#shift
:当然,要执行
Array#push
,您只需使用其中一种连接方法:要模拟 Array#unshift ,您可以使用 String#insert ,这实际上很像切片的逆操作:
您还可以从使用切片以多种方式在字符串中间。
首先,您可以传递起始位置和长度:
您还可以传递 Range 对象来获取绝对位置:
在 Ruby 1.9 中,使用
String#slice
与String#[]< 相同/code>,但如果您使用 bang 方法
String#slice!
它实际上会删除您指定的子字符串。这是一个稍微复杂一点的示例,我们重新实现了
String#gsub!
的简单版本来执行搜索和替换:当然,99.999% 的情况下,您会想要使用前面提到的 < code>String.gsub! 会做完全相同的事情:
参考文献:
String#slice!
andString#insert
is going to get you much closer to what you want without converting your strings to arrays.For example, to simulate
Array#pop
you can do:Likewise, for
Array#shift
:Naturally, to do an
Array#push
you just use one of the concatenation methods:To simulate
Array#unshift
you useString#insert
instead, it's a lot like the inverse of slice really:You can also grab chunks from the middle of a string in multiple ways with slice.
First you can pass a start position and length:
And you can also pass a Range object to grab absolute positions:
In Ruby 1.9 using
String#slice
like this is identical toString#[]
, but if you use the bang methodString#slice!
it will actually remove the substring you specify.Here's a slightly more complex example where we reimplement a simple version of
String#gsub!
to do a search and replace:Of course 99.999% of the time, you're going to want to use the aforementioned
String.gsub!
which will do the exact same thing:references: