如何在Ruby中将一个字符串拆分成两个变量,且只用一行代码实现?

3
在Ruby中,我如何在一行代码中将字符串拆分为两个变量?
示例:
目标:将字符串s拆分为变量a和b,使得a = 'A',b = 123。
irb(main):001:0> s = "A123" # Create string to split.
=> "A123"

irb(main):002:0> a, b = s.split(/\d/) # Extracts letter only.
=> ["A"]

irb(main):003:0> puts a # a got assigned 'A' as expected.
A
=> nil

irb(main):004:0> puts b # b did not get assigned the split remainder, '123'.
=> nil

irb(main):005:0> b = s.split(/\D/) # Extracts number only.
=> ["", "123"]

irb(main):006:0> puts b # Now b has the value I want it to have.
123
=> nil

如何用一行代码实现相同的结果?

1
你的字符串是否总是只包含一个非数字字符和一个或多个数字? - Wiktor Stribiżew
@WiktorStribiżew - 不,它包含x个非数字,后跟x个数字(始终按照此顺序)。 - leifericf
好的,格式非常简单,您可以使用以下任何解决方案。 - Wiktor Stribiżew
我不明白为什么人们如此痴迷于用“一行代码”来完成任务。在Ruby中,换行符总是可以被删除的。每个 Ruby 代码都可以写成一行。但这是否使代码更好呢?例如,在你的例子中:a = s.split(/\d/); b = s.split(/\D/)。一行代码。但这是否真的让它变得更好了呢? - Jörg W Mittag
3个回答

10

有很多种方法,例如在这种特定情况下使用正向后行断言

a, b = 'A123'.split(/(?<=\D)/)
#⇒ ["A", "123"]

具有切片限制的正向先行断言:

'AB123'.split(/(?=\d)/, 2)
#⇒ ["AB", "123"]

按索引:

[0..1, 2..-1].map &'AB123'.method(:[])
#⇒ ["AB", "123"]

太好了,谢谢 - 这正是我在寻找的。只要时间允许,我会尽快接受这个答案 :) - leifericf

5

不必使用环视来拆分字符串,您可以使用 /\d+|\D+/ 将字符串扫描成数字和非数字的标记:

"AB123".scan(/\d+|\D+/)
# => [AB, 123]

该模式匹配

  • \d+ - 一个或多个数字
  • | - 或者
  • \D+ - 一个或多个非数字字符。

太好了!我发现这种方法比前瞻和后顾更易读。这两种方法有什么优缺点吗? - leifericf
1
它取决于您收到的输入字符串以及您最终需要获取什么。对于像您发布的那种字符串类型,这并不重要。如果您收到 A123BC345GHJ6768 并且需要将其拆分为数字-非数字标记,则我的方法似乎是正确的,更为直接。您可以查看此正则表达式演示 - Wiktor Stribiżew

1
另一个示例,通过 MatchData#to_a 实现:
_, a, b = * "AB123".match(/(\D+)(\d+)/)
#=> ["AB123", "AB", "123"]

a #=> "AB"
b #=> "123"

最微小的细节:您可以编写a,b = *“AB123”。match(/(\ D +)(\ d +)/)。drop(1),这也适用于链接。 - Cary Swoveland
当然可以。一个人可以写成a,b = *“AB12a3”。match(/(\ D +)(\ d +)/)[1..-1],但如果没有匹配就会引发异常。根据问题的解释,可能需要锚点。 - Cary Swoveland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接