如果我们有一个像“1,2,3,4,5”这样的字符串,并且我们使用拆分函数解析它以获取各个元素,Ruby 会为每个元素分配一个新的字符串对象。如果你处理一个大文件,它有很多重复值,例如很多 0,那么返回卡住字符串将节省大量时间和内存,因为解释器不必创建这些新对象——它可以返回一个引用卡住的字符串 - 并且不需要在它们之后清理。
所以不是这样:(每个字符串对象都是唯一的)
2.4.1 :007 > "1,2,3,4,5,6".split(',').map(&:object_id)
=> [70280975267840, 70280975267820, 70280975267800, 70280975267780, 70280975267760, 70280975267740]
2.4.1 :008 > "1,2,3,4,5,6".split(',').map(&:object_id)
=> [70280978671420, 70280978671400, 70280978671380, 70280978671360, 70280978671340, 70280978671320]
我想看到这个:(我们在第一次和第二次运行中得到相同的字符串对象)
2.4.1 :007 > "1,2,3,4,5,6".split(',').map(&:object_id)
=> [70280975267840, 70280975267820, 70280975267800, 70280975267780, 70280975267760, 70280975267740]
2.4.1 :008 > "1,2,3,4,5,6".split(',').map(&:object_id)
=> [70280975267840, 70280975267820, 70280975267800, 70280975267780, 70280975267760, 70280975267740]
当然,这需要某种选择加入机制,例如允许您指定要使用的卡住字符串列表,因为卡住文件中的每个单词听起来像是自找麻烦。
理想情况下,界面应该是这样的:
"1,2,3,4,5,6".split(',', frozen_strings: [-'1', -'2', -'3', -'4', -'5', -'6'])
有没有办法在不编写 C 扩展的情况下在 Ruby 中执行此操作?也许使用一些外部库,如 CSV 解析器?
最佳答案
您可以通过 String#-@
获得卡住的、去重的字符串.
要么我使用 map
:
str = '1,1,2,2'
str.split(',').map(&:-@).map(&:object_id)
#=> [70293234167580,
# 70293234167580,
# 70293368908400,
# 70293368908400]
或者,在处理一个巨大的字符串时使用 block 形式来节省内存:(Ruby 2.6+)
def frozen_split(str, pattern)
return enum_for(__method__, str, pattern) unless block_given?
str.split(pattern) { |x| yield -x }
end
并通过以下方式调用它:
frozen_split(str, ',').map(&:object_id)
#=> [70293234167580,
# 70293234167580,
# 70293368908400,
# 70293368908400]
关于ruby - 是否可以从 Ruby 中的 String#split 函数返回卡住的、去重的字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63631385/