子字符串在"hello"[0..2]
返回"hel"
是否有整数等值,返回子位,如9[1..3]
返回4
或"100"
?
上下文:
我试图做一个遗传算法,并且有一个跨越阶段,你将两条染色体分成两部分,然后交换一半,例如"10101010"
与"00000000"
的{{1}}交叉i = 4
将为"00001010", "10100000"
但是,我这样做了几百万次,所以使用字符串效率很低,有没有一种方法可以做到这一点?
答案 0 :(得分:1)
您可以考虑优化类Fixnum以允许Fixnum#[]的参数为位索引或位索引范围。
module StabBitRange
def [](arg)
case arg
when Range
mask = arg.reduce(0) { |n, idx| n |= (1 << idx) }
(self & mask) >> arg.first
else
super
end
end
end
module StabBits
refine Fixnum do
prepend StabBitRange
end
end
请参阅Refinements和Module#prepend。 Prepend StabBitRange
将其中包含的方法(此处只有一个)移动到祖先链中Fixnum
中具有相同名称的方法之前。替代方法(在Ruby v2.0中引入Prepend
之前常用)是别名Fixnum#[]
,然后将Fixnum[]
重新定义为采用位索引或范围的新方法比特指数。 (请参阅此答案的编辑历史以了解如何完成此操作。)我希望读者同意Prepend
是一种更明智的方法。
要使此代码可供使用,我们只需要调用关键字using
。
using StabBits
n = 682
n.to_s(2) #=> "1010101010"
n[0] #=> 0
n[1] #=> 1
n[2] #=> 0
n[0..7] #=> 170 170.to_s(2) => "10101010"
n[1..7] #=> 85 85.to_s(2) => "1010101"
n[2..6] #=> 10 10.to_s(2) => "1010"
当调用StabBitRange#\[\]
并且参数不是范围时,super
会调用Fixnum#[]
并传递参数。该方法处理参数错误,并在没有错误时返回所需的位。
在IRB中运行此代码时,会引发以下异常:RuntimeError: main.using is permitted only at top level
。那是因为IRB运行在顶层,但是从Ruby解析器的角度来看,在IRB中运行的代码运行在更高级别。要在IRB中运行它,必须将using StabBits
和代码包含在模块中。