发表于:2006.03.08 00:12
分类: Ruby Way 翻译
出处:http://my4java.itpub.net/post/9983/57955
---------------------------------------------------------------
19、Obscuring Strings
有时候我们不想字符串可被轻易阅读。例如,口令不应被以纯文本格式保存,不管如何设置文件的许可。
标准方法crypt使用DES加密字符串。它接受一个"salt"值做为参数(类似于随机数生成器的seed种子值)。
下面显示了对它的一个很小应用,我们在这儿要求口令。
coded = "hfCghHIE5LAM."
puts "Speak, friend, and enter!"
print "Password: "
password = gets.chop
if password.crypt("hf") == coded
puts "Welcome!"
else
puts "What are you, an orc?"
end
还有另一种用于隐藏字符串方法。例如,我们有时候想隐藏文件中的字符串,以便它们不会被轻易阅读。甚至二进制文件都可用Unix字符串实用工具或其它来轻易地阅读一部分。而DES加密则更牢固一些。
值得注意的是,你不要在Web应用程序的服务器端来进行加密。这是因为进入Web的口令以明文形式在互联网上传输。像这种情况,最容易的安全措施是使用SSL。当然,你还可以使用对服务器端的加密,但是理由不同,是为了保护口令的存储而不是在传输期间。
s1 = "abracadabra"
a = s1.count("c") # 1
b = s1.count("bdr") # 5
字符串参数类似于非常简单的正则表达式。如果以脱字符号^开始,列表内的将被否定。
c = s1.count("^a") # 6
d = s1.count("^bdr") # 6
连字号-指出字符的范围。
e = s1.count("a-d") # 9
21、反转字符串
字符串可以被reverse方法(相应有reverse!)轻易地反转。
s1 = "Star Trek"
s2 = s1.reverse # "kerT ratS"
s1.reverse! # s1 is now "kerT ratS"
假设你有个句子需要反转单词的次序(而不是字符的次序)。使用%w操作符生成单词数组,反转这个数组,然后使用join方法将它们重新连在一起。
words = %w( how now brown cow )
# ["how", "now", "brown", "cow"]
words.reverse.join(" ")
# "cow brown now how"
可以使用更一般化的String#split,它允许按你自己的模式分离单词。
phrase = "Now here's a sentence"
phrase.split(" ").reverse.join(" ")
22、移除重复字符
使用squeeze方法可以移除重复的字符。
s1 = "bookkeeper"
s2 = s1.squeeze # "bokeper"
s3 = "Hello..."
s4 = s3.squeeze # "Helo."
如果指定参数,则只有这些字符被压缩。
s5 = s3.squeeze(".") # "Hello."
这个参数遵循与count方法一样的规则;也就是说,它理解脱字符号和连字符。
如果做为参数传递过来的字符出现在列表中,则delete方法将删除字符。
s1 = "To be, or not to be"
s2 = s1.delete("b") # "To e, or not to e"
s3 = "Veni, vidi, vici!"
s4 = s3.delete(",!") # "Veni vidi vici"
这个参数遵循与count方法一样的规则;也就是说,它理解脱字符号和连字符。
也有delete!方法。
dump方法将明确提供可打印的字符,它们通常有可见与不可见之分。
s1 = "Listen" << 7 << 7 << 7 # Add three ASCII BEL characters
puts s1.dump # Prints: Listen070707
s2 = "abcttdeftghinn"
puts s2.dump # Prints: abcttdeftghinn
s3 = "Double quote: ""
puts s3.dump # Prints: Double quote: "
25、生成连续字符串
我们很少想查找一个字符串连续值;例如,"aaa"的连续值是"aab"(然后是"aac", "aad",等等)。
Ruby提供了succ方法来达到这个目的。
droid = "R2D2"
improved = droid.succ # "R2D3"
pill = "Vitamin B"
pill2 = pill.succ # "Vitamin C"
我们不推荐使用这个特性,除非值是可预见的和合理的。如果你的字符串足够长,你会得出令人不可思议的结果。
还有个upto方法,它将在循环中重复地应用succ方法,直到获得期望的值。
"Files, A".upto "Files, X" do |letter|
puts "Opening: #{ letter} "
end
# Produces 24 lines of output
相反,我们不主张频繁地使用它,使用它你会冒风险。同样,我们也想指出,在写本书时,还没有能替代它的相应的处理函数。
26、Calculate the Levenstein Distance Between Two Strings
两个字符串之间距离的概念在智能语言(AI),密码系统,蛋白质搜索等其它领域都很重要。
The Levenstein distance (see Listing 2.3) is the minimum number of modifications needed to change one string into another, using three basic modification operations:
Listing 2.3 Levenstein Distance
class String
def levenstein(other, ins=2,
# ins,
return nil if self.nil?
return nil if other.nil?
dm = [] # distance matrix
# Initialize first row values
dm[0] = (0..self.length).collect { |i| i * ins }
fill = [0] * (self.length - 1)
# Initialize first column values
for i in 1..other.length
dm[i] = [i *
end
# populate matrix
for i in 1..other.length
for j in 1..self.length
# critical comparison
dm[i][j] = [
dm[i-1][j-1] +
(self[j-1] == other[i-1] ? 0 : sub),
dm[i][j-1] + ins,
dm[i-1][j] +
].min
end
end
# The last value in matrix is the
# Levenstein distance between the strings
dm[other.length][self.length]
end
end
s1 = "ACUGAUGUGA"
s2 = "AUGGAA"
d1 = s1.levenstein(s2) # 9
s3 = "
s4 = "pencilvaneya"
d2 = s3.levenstein(s4) # 7
s5 = "abcd"
s6 = "abcd"
现在,我们已经定义了Levenstein距离,可以想像得到我们的类似定义?方法,以同样方式给出的。
class String
def similar?(other, thresh=2)
if self.levenstein(other) < thresh
true
else
false
end
end
end
if "polarity".similar?("hilarity")
puts "Electricity is funny!"
end
Of course, it would also be possible to pass in the three weighted costs to the similar? method so that they could in turn be passed into the Levenstein method. We have omitted these for simplicity.
可以将字符串视为堆栈或队列(见Listing2.4),添加操作shift,unshift,push,pop,rotate_left,和rotate_right。这些操作符有字符和单词两个级别。我们写一或二个程序来检验它们功能。当然,你也可以自己来做。
每个方法的返回值可能有些混乱。在重新取回操作符如pop或shift情况下,返回值是被重新取回的条目。在存储操作如push或unshift情况下,返回值是个新字符串。在所有旋转操作符情况下,返回值也是新字符串。我们在清晰地说一下:这些操作符的每一个都修改它接收者,尽管它们们没有使用感叹号!做为后缀标记出来。
class String
def shift
# 从self移除第一个字符并返回它,修改self。
return nil if self.empty?
item=self[0]
self.sub!(/^./,"")
return nil if item.nil?
item.chr
end
def unshift(other)
# 将other字符串的最后一个字符添加到self的前面。
newself = other.to_s.dup.pop.to_s + self
self.replace(newself)
end
def pop
# 弹出self的最后一个字符并返回它,修改self。
return nil if self.empty?
item=self[-1]
self.chop!
return nil if item.nil?
item.chr
def push(other)
#将other的第一个字符放到self的尾部。
newself = self + other.to_s.dup.shift.to_s
self.replace(newself)
end
def rotate_left(n=1)
n=1 unless n.kind_of? Integer
n.times do
char = self.shift
self.push(char)
end
self
end
def rotate_right(n=1)
n=1 unless n.kind_of? Integer
n.times do
char = self.pop
self.unshift(char)
end
self
end
@@first_word_re = /^(w+W*)/
@@last_word_re = /(w+W*)$/
def shift_word
# Shifts first word off of self
# and returns; changes self
return nil if self.empty?
self=~@@first_word_re
newself= $' || "" # $' is POSTMATCH
self.replace(newself) unless $'.nil?
$1
def unshift_word(other)
# Adds provided string to front of self
newself = other.to_s + self
self.replace(newself)
end
def pop_word
# Pops and returns last word off
# self; changes self
return nil if self.empty?
self=~@@last_word_re
newself= $` || "" # $` is PREMATCH
self.replace(newself) unless $`.nil?
$1
end
def push_word(other)
# Pushes provided string onto end of self
newself = self + other.to_s
self.replace(newself)
end
def rotate_word_left
word = self.shift_word
self.push_word(word)
end
def rotate_word_right
word = self.pop_word
self.unshift_word(word)
end
alias rotate_Left rotate_word_left
alias rotate_Right rotate_word_right
# ------------
str = "Hello there"
puts str.rotate_left # "ello thereH"
puts str.pop # "H"
puts str.shift # "e"
puts str.rotate_right # "ello ther"
puts str.unshift("H") # "Hello ther"
puts str.push("e") # "Hello there"
puts str.push_word(", pal!") # "Hello there, pal!"
puts str.rotate_Left # "there, pal!Hello "
puts str.pop_word # str is "there, pal!"
# result is "Hello "
puts str.shift_word # str is "pal!"
# result is "there, "
puts str.unshift_word("Hi there, ") # "Hi there, pal!"
puts str.rotate_Right # "pal!Hi there, "
puts str.rotate_left(4) # "Hi there, pal!"
puts "Trying again..."
str = "pal! Hi there, "
puts str.rotate_left(5) # "Hi there, pal!"
注意带有范围的[ ]操作符被用于Note that the [] operator with a range might be used to gain a window onto a string that is being rotated.
str = ".....duck....*...*..*..........*......*..."
loop do
print str.rotate_left[0..7],"r"}
end
# speed reading
string="See Bill run. Run Bill run! See Jane sit. Jane sees Bill."






