当前位置:  开发笔记 > 后端 > 正文

Ruby中的字符串连接

如何解决《Ruby中的字符串连接》经验,为你挑选了10个好方法。

我正在寻找一种更优雅的方式来连接Ruby中的字符串.

我有以下几行:

source = "#{ROOT_DIR}/" << project << "/App.config"

这样做有更好的方法吗?

就此而言,<<和之间的区别是+什么?



1> Keltia..:

您可以通过以下几种方式实现:

    如你所示,<<但这不是通常的方式

    使用字符串插值

    source = "#{ROOT_DIR}/#{project}/App.config"
    

    +

    source = "#{ROOT_DIR}/" + project + "/App.config"
    

第二种方法在内存/速度方面似乎比我看到的更有效(虽然没有测量).当ROOT_DIR为零时,所有三种方法都会抛出未初始化的常量错误.

处理路径名时,您可能希望使用File.join以避免弄乱路径名分隔符.

最后,这是一个品味问题.


而不是使用<<在数组的元素上,使用Array#join,它更快.
我对红宝石不太熟悉.但通常在连接大量字符串的情况下,通常可以通过将字符串附加到数组然后最后将字符串原子化放在一起来获得性能.那么<<可能有用吗?

2> Matt Burke..:

+操作是正常级联选择,可能是连接字符串的最快方法.

+和之间的区别<<<<改变左侧的对象,而+不是.

irb(main):001:0> s = 'a'
=> "a"
irb(main):002:0> s + 'b'
=> "ab"
irb(main):003:0> s
=> "a"
irb(main):004:0> s << 'b'
=> "ab"
irb(main):005:0> s
=> "ab"


+运算符绝对不是连接字符串的最快方法.每次使用它时,它都会复制,而<<连接到位并且性能更高.
您的jruby结果会因早期运行的JVM重载而导致插值偏差.如果您为每个解释器多次运行测试套件(在同一个过程中 - 所以将所有内容包含在"5.times do ... end"块中),您最终会获得更准确的结果.我的测试显示插值是所有Ruby解释器中最快的方法.我本以为```是最快的,但这就是我们基准测试的原因.
对于大多数用途,插值,`+`和`<<`将大致相同.如果你正在处理很多字符串,或者很大的字符串,那么你可能会注意到一个区别.我们对他们的表现有多么惊讶.https://gist.github.com/2895311

3> 小智..:

如果您只是连接路径,则可以使用Ruby自己的File.join方法.

source = File.join(ROOT_DIR, project, 'App.config')


这似乎是要走的路,因为ruby将负责使用不同的路径分隔符在系统上创建正确的字符串.

4> Danny..:

来自http://greyblake.com/blog/2012/09/02/ruby-perfomance-tricks/

使用<<aka concat远比使用aka 更有效+=,因为后者创建一个时态对象并用新对象覆盖第一个对象.

require 'benchmark'

N = 1000
BASIC_LENGTH = 10

5.times do |factor|
  length = BASIC_LENGTH * (10 ** factor)
  puts "_" * 60 + "\nLENGTH: #{length}"

  Benchmark.bm(10, '+= VS <<') do |x|
    concat_report = x.report("+=")  do
      str1 = ""
      str2 = "s" * length
      N.times { str1 += str2 }
    end

    modify_report = x.report("<<")  do
      str1 = "s"
      str2 = "s" * length
      N.times { str1 << str2 }
    end

    [concat_report / modify_report]
  end
end

输出:

____________________________________________________________
LENGTH: 10
                 user     system      total        real
+=           0.000000   0.000000   0.000000 (  0.004671)
<<           0.000000   0.000000   0.000000 (  0.000176)
+= VS <<          NaN        NaN        NaN ( 26.508796)
____________________________________________________________
LENGTH: 100
                 user     system      total        real
+=           0.020000   0.000000   0.020000 (  0.022995)
<<           0.000000   0.000000   0.000000 (  0.000226)
+= VS <<          Inf        NaN        NaN (101.845829)
____________________________________________________________
LENGTH: 1000
                 user     system      total        real
+=           0.270000   0.120000   0.390000 (  0.390888)
<<           0.000000   0.000000   0.000000 (  0.001730)
+= VS <<          Inf        Inf        NaN (225.920077)
____________________________________________________________
LENGTH: 10000
                 user     system      total        real
+=           3.660000   1.570000   5.230000 (  5.233861)
<<           0.000000   0.010000   0.010000 (  0.015099)
+= VS <<          Inf 157.000000        NaN (346.629692)
____________________________________________________________
LENGTH: 100000
                 user     system      total        real
+=          31.270000  16.990000  48.260000 ( 48.328511)
<<           0.050000   0.050000   0.100000 (  0.105993)
+= VS <<   625.400000 339.800000        NaN (455.961373)



5> Dejan Simic..:

由于这是一条路径,我可能会使用数组和连接:

source = [ROOT_DIR, project, 'App.config'] * '/'



6> Adobe..:

这是另一个受这个要点启发的基准.它比较动态和预定义字符串的concatenation(+),appending(<<)和interpolation(#{}).

require 'benchmark'

# we will need the CAPTION and FORMAT constants:
include Benchmark

count = 100_000


puts "Dynamic strings"

Benchmark.benchmark(CAPTION, 7, FORMAT) do |bm|
  bm.report("concat") { count.times { 11.to_s +  '/' +  12.to_s } }
  bm.report("append") { count.times { 11.to_s << '/' << 12.to_s } }
  bm.report("interp") { count.times { "#{11}/#{12}" } }
end


puts "\nPredefined strings"

s11 = "11"
s12 = "12"
Benchmark.benchmark(CAPTION, 7, FORMAT) do |bm|
  bm.report("concat") { count.times { s11 +  '/' +  s12 } }
  bm.report("append") { count.times { s11 << '/' << s12 } }
  bm.report("interp") { count.times { "#{s11}/#{s12}"   } }
end

输出:

Dynamic strings
              user     system      total        real
concat    0.050000   0.000000   0.050000 (  0.047770)
append    0.040000   0.000000   0.040000 (  0.042724)
interp    0.050000   0.000000   0.050000 (  0.051736)

Predefined strings
              user     system      total        real
concat    0.030000   0.000000   0.030000 (  0.024888)
append    0.020000   0.000000   0.020000 (  0.023373)
interp    3.160000   0.160000   3.320000 (  3.311253)

结论:MRI中的插值很重.



7> tig..:

我更喜欢使用路径名:

require 'pathname' # pathname is in stdlib
Pathname(ROOT_DIR) + project + 'App.config'

关于<<+红宝石文档:

+:返回一个新的 String,其中包含连接到str的other_str

<<:将给定对象连接到str.如果对象是0到255之间的Fixnum,则在连接之前将其转换为字符.

所以区别在于第一个操作数变为什么(<<进行了更改,+返回新的字符串,因此内存更重),如果第一个操作数是Fixnum将会是什么(<<将添加好像是代码等于该数字的字符,+将会提高错误)


我只是发现在路径名上调用'+'可能很危险,因为如果arg是绝对路径,则接收器路径将被忽略:`Pathname('/ home / foo')+'/ etc / passwd'#=># <路径名:/ etc / passwd>`。这是基于rubydoc示例设计的。似乎File.join更安全。

8> Marcio Manga..:

让我向你展示我的所有经验.

我有一个返回32k记录的查询,对于每个记录,我调用一种方法将该数据库记录格式化为格式化字符串,然后将其连接成一个字符串,在所有这个过程结束时将转换为磁盘中的文件.

我的问题是,据记录,大约24k,连接字符串的过程导致痛苦.

我正在使用常规的'+'运算符.

当我改为'<<'时就像魔术一样.真的很快.

所以,我记得我的旧时代 - 有点像1998年 - 当我使用Java并使用'+'连接String并从String更改为StringBuffer时(现在我们Java开发人员拥有StringBuilder).

我相信Ruby世界中+/<<的过程与Java世界中的+/StringBuilder.append相同.

第一个在内存中重新分配整个对象,另一个只是指向一个新地址.



9> 小智..:

以下是更多方法:

"String1" + "String2"

"#{String1} #{String2}"

String1<

等等 ...



10> Boris Stitni..:

连说你说?怎么样的#concat方法呢?

a = 'foo'
a.object_id #=> some number
a.concat 'bar' #=> foobar
a.object_id #=> same as before -- string a remains the same object

平心而论,concat是别名<<.


还有一种方法可以将其他人没有提到的字符串粘合在一起,这仅仅是并置:`"foo""bar"'baz"#=>"foobarabaz"`
推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有