ruby 删除和替换字符串中某个字符之前的所有字符

jmp7cifd  于 2023-04-05  发布在  Ruby
关注(0)|答案(3)|浏览(153)

我想删除和替换字符串中某个字符之前的所有字符。例如,“045723456789”,我想成为“+44723456789”,通过删除“7”之前的所有字符,并将其替换为“+44”,在Ruby中。我需要在没有任何库的情况下这样做,例如,regex

huus2vyu

huus2vyu1#

前言

任意约束的家庭作业(看起来像是这样)要么会有你的老师提供的预期答案--在这种情况下,要么重读你的课程材料,要么 * 向你的老师 * 寻求指导;这就是他们被支付的!-或者答案应该与你正在学习的材料有关,并包含一个合适的答案。
如果没有一些教育性的观点,这个约束就是任意的。即使你可以用其他方法来做,正则表达式可能比其他解决方案更慢,但更具有泛化性。也就是说,你当然可以采取其他方法来解决这个问题。

使用String方法

在Ruby中,String methods通常比正则表达式快得多,但并不是最适合所有用例的。在您的情况下,String#sub方法会更简单,更习惯,并且可以使用字符串而不是正则表达式进行匹配,但是如果没有正则表达式,你就必须更加努力地隔离或锚你想要替换的文本。你可以用各种不依赖正则表达式的String方法做你想做的事情,但是你仍然需要考虑这个假设的可靠性,你总是可以用其他东西替换前三个字符。

缺少规格

无regex解决方案最困难的部分在于根据您尚未提供的规范选择最佳解决方案,例如:
1.除了示例中提供的单个输入之外,您是否还需要将此应用于其他数字?
1.所有电话号码包含相同数量的字符吗?
1.所有替换前缀是否相同?
1.是否有其他子字符串需要替换?
1.在进行替换之前,是否需要担心给定的String是否与其他String或模式匹配?
我可以继续说下去,但你明白我的意思。

假设

由于我们没有完整的规范,让我们做一些假设来使它更容易。下面是我为了提供解决方案而做的一些假设。如果这些假设无效,可能的解决方案空间将发生变化。
1.要替换的前缀既不是固定字符串,也不是固定长度。
1.不保证要替换的前缀在输入字符串中是唯一的。
1.要保留的有效位数的长度可能会有所不同。

  1. String的有效右侧部分(要替换的前缀之后的部分)的长度是固定大小,或者其长度为调用方法所知。
    1.您希望专门使用不暴露正则表达式的String方法,无论它们是否在Ruby内部实现为字符串或正则表达式模式匹配。
    如果这些假设仍然有效,那么我们就可以得到许多固定字符串和基于字符的解决方案,我将只提出其中的一个。其他解决方案也是可能的,因此您的里程可能会有所不同。

带替换前缀的固定字符串解决方案

这里有一个相当灵活的解决方案,它只基于按定义的尾随长度对输入字符串进行切片,而不是基于模式匹配。

# Return a String containing a phone number with
# a new prefix prepended to a suffix of defined
# length.
#
# @param str [String] a phone number with a
#   suffix of +sfx_len+ valid digits
# @param sfx_len [Integer] suffix length is the
#   negated absolute value of the number of
#   characters extracted from the right-most
#   side of +str+
# @param prefix [String] new country code that
#   will be prepended to the trimmed +str+
# @raise [TypeError] when trying to append to 
#   +prefix+ when +str[]+ returns nil; for
#   example, this will happen if the +sfx_len+
#   exceeds the number of characters in +str+
# @return [String] modified phone number with
#   prefixed with a new country code
def apply_prefix str, sfx_len=9, prefix="+44"
  prefix + str[-(sfx_len.abs)..-1]
end

apply_prefix "045723456789"
#=> "+44723456789"

使用String#delete_prefix的其他解决方案也是可能的,但是这样的解决方案不符合我们当前的假设。String#sub也不符合,即使使用固定的字符串模式,除非你能保证相同的字符模式永远不会出现在电话号码中,从而可以避免使用正则表达式原子进行锚定。所提供的解决方案本身不需要锚定。但是它 * 确实 * 要求调用者知道在9的默认后缀长度不总是正确的情况下,str 中有多少个字符将被认为是有效的。

xmakbtuz

xmakbtuz2#

我可能会像@卡里Swoveland已经建议的那样做,但另一个选择是使用partition

def prefixer(str, ch, replace)
  "#{replace}#{str.partition(ch)[1, 2].join}"
end

prefixer("045723456789", "7", "+44")
#=>  "+44723456789"

prefixer("045123456789", "7", "+44")
#=>  "+44789"

prefixer("045123456189", "7", "+44")
#=>  "+44"

我显然做了很多假设,特别是如果ch不是第4个字符,以及如果ch根本不存在于字符串中,会发生什么。

ttygqcqt

ttygqcqt3#

def remove_and_replace(str, ch, replace)
  i = str.index(ch)
  i.nil? ? nil : replace + str[i..]
end
remove_and_replace("045723456789", "7", "+44")    #=> "+44723456789"
remove_and_replace("045123456789", "7", "+44")    #=> "+44789"
remove_and_replace("045123456189", "7", "+44")    #=> nil

请参阅String#index和String#concat。

相关问题