Ruby:1.9 中字符串不再混合在 Enumerable 中

发布于 2024-08-21 18:46:50 字数 122 浏览 2 评论 0原文

那么我怎样才能仍然能够编写漂亮的代码,例如:

'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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

会傲 2024-08-28 18:46:50

它不是可枚举字符串实际枚举的内容。字符串是……

  • 行、
  • 字符、
  • 代码点或
  • 字节的序列吗?

答案是:所有这些、其中任何一个、其中之一或两者都不是,具体取决于上下文。因此,您必须告诉 Ruby 您真正想要哪一个。

String 类中有多种方法可以返回上述任何一个的枚举器。如果您想要 1.9 之前的行为,您的代码示例将是

'im a string meing!'.bytes.to_a.pop

这看起来有点难看,但这是有原因的:字符串是一个序列。您将其视为堆栈。堆栈不是序列,事实上它几乎是序列的反面。

It is not what an enumerable string atually enumerates. Is a string a sequence of ...

  • lines,
  • characters,
  • codepoints or
  • bytes?

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 be

'im a string meing!'.bytes.to_a.pop

This 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.

谢绝鈎搭 2024-08-28 18:46:50

这不太漂亮:)

另外 #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.

灼痛 2024-08-28 18:46:50

既然你不喜欢 str[str.length],那么

'im a string meing!'[-1]  # returns last character as a character value

or

'im a string meing!'[-1,1]  # returns last character as a string

or 怎么样,如果你还需要对其进行适当的修改,同时保持它是一个简单的单行:

class String
  def pop
    last = self[-1,1]
    self.chop!
    last
  end
end

Since you don't like str[str.length], how about

'im a string meing!'[-1]  # returns last character as a character value

or

'im a string meing!'[-1,1]  # returns last character as a string

or, if you need it modified in place as well, while keeping it an easy one-liner:

class String
  def pop
    last = self[-1,1]
    self.chop!
    last
  end
end
笑红尘 2024-08-28 18:46:50
#!/usr/bin/ruby1.8

s = "I'm a string meing!"
s, last_char = s.rpartition(/./)
p [s, last_char]    # => ["I'm a string meing", "!"]

String.rpartition 是 1.9 中的新增内容,但已向后移植到 1.8.7。它从字符串末尾开始向后搜索正则表达式。它返回匹配之前的字符串部分、匹配的部分以及匹配之后的字符串部分(我们在这里将其丢弃)。

#!/usr/bin/ruby1.8

s = "I'm a string meing!"
s, last_char = s.rpartition(/./)
p [s, last_char]    # => ["I'm a string meing", "!"]

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).

獨角戲 2024-08-28 18:46:50

String#slice!String#insert 将使您更接近您想要的内容,而无需将字符串转换为数组。

例如,要模拟 Array#pop,您可以执行以下操作:

text = '¡Exclamation!'
mark = text.slice! -1

mark == '!'          #=> true
text                 #=> "¡Exclamation"

同样,对于 Array#shift

text = "¡Exclamation!"
inverted_mark = text.slice! 0

inverted_mark == '¡' #=> true
text                 #=> "Exclamation!"

当然,要执行 Array#push,您只需使用其中一种连接方法:

text = 'Hello'
text << '!'          #=> "Hello!"
text.concat '!'      #=> "Hello!!"

要模拟 Array#unshift ,您可以使用 String#insert ,这实际上很像切片的逆操作:

text = 'World!'
text.insert 0, 'Hello, ' #=> "Hello, World!"

您还可以从使用切片以多种方式在字符串中间。

首先,您可以传递起始位置和长度:

text = 'Something!'
thing = text.slice 4, 5

您还可以传递 Range 对象来获取绝对位置:

text = 'This is only a test.'
only = text.slice (8..11)

在 Ruby 1.9 中,使用 String#sliceString#[]< 相同/code>,但如果您使用 bang 方法 String#slice! 它实际上会删除您指定的子字符串。

text = 'This is only a test.'
only = text.slice! (8..12)
text == 'This is a test.'      #=> true

这是一个稍微复杂一点的示例,我们重新实现了 String#gsub! 的简单版本来执行搜索和替换:

text = 'This is only a test.'
search = 'only'
replace = 'not'

index = text =~ /#{search}/
text.slice! index, search.length
text.insert index, replace

text == 'This is not a test.'  #=> true

当然,99.999% 的情况下,您会想要使用前面提到的 < code>String.gsub! 会做完全相同的事情:

text = 'This is only a test.'
text.gsub! 'only', 'not' 

text == 'This is not a test.'  #=> true

参考文献:

String#slice! and String#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:

text = '¡Exclamation!'
mark = text.slice! -1

mark == '!'          #=> true
text                 #=> "¡Exclamation"

Likewise, for Array#shift:

text = "¡Exclamation!"
inverted_mark = text.slice! 0

inverted_mark == '¡' #=> true
text                 #=> "Exclamation!"

Naturally, to do an Array#push you just use one of the concatenation methods:

text = 'Hello'
text << '!'          #=> "Hello!"
text.concat '!'      #=> "Hello!!"

To simulate Array#unshift you use String#insert instead, it's a lot like the inverse of slice really:

text = 'World!'
text.insert 0, 'Hello, ' #=> "Hello, World!"

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:

text = 'Something!'
thing = text.slice 4, 5

And you can also pass a Range object to grab absolute positions:

text = 'This is only a test.'
only = text.slice (8..11)

In Ruby 1.9 using String#slice like this is identical to String#[], but if you use the bang method String#slice! it will actually remove the substring you specify.

text = 'This is only a test.'
only = text.slice! (8..12)
text == 'This is a test.'      #=> true

Here's a slightly more complex example where we reimplement a simple version of String#gsub! to do a search and replace:

text = 'This is only a test.'
search = 'only'
replace = 'not'

index = text =~ /#{search}/
text.slice! index, search.length
text.insert index, replace

text == 'This is not a test.'  #=> true

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:

text = 'This is only a test.'
text.gsub! 'only', 'not' 

text == 'This is not a test.'  #=> true

references:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文