Ruby

没有什么特别的原因开学学习Ruby,只是从兴趣出发

Programming Ruby 2nd Edition

特殊变量

$! 最近一次的错误信息
$@ 错误产生的位置
$_ gets最近读的字符串
$. 解释器最近读的行数(line number)
$& 最近一次与正则表达式匹配的字符串
$~ 作为子表达式组的最近一次匹配
$n 最近匹配的第n个子表达式(和$~[n]一样)
$= 是否区别大小写的标志
$/ 输入记录分隔符
$\ 输出记录分隔符
$0 Ruby脚本的文件名
$* 命令行参数
$$ 解释器进程ID
$? 最近一次执行的子进程退出状态

Enumerable

分组迭代

以前我们所介绍的迭代都是每次迭代一个元素,如果我们想要迭代一个组的时候,我们可以使用each_slice
require 'enumerator'

arr = [1,2,3,4,5,6,7,8,9,10]
arr.each_slice(3) do |triple|
  puts triple.join(",")
end
#这里传入的3,也就意味着,每次传进去三个元素.
# Output:
# 1,2,3
# 4,5,6
# 7,8,9
# 10

partition 方法

简而言之,partition 方法就是用来分组的,也就是说,它可以将一个数组根据一定的规则分为不同的组
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]

odd_even = nums.partition {|x| x % 2 == 1 }
# [[1,3,5,7,9],[2,3,4,6,8]]           #分组后产生多维数组

under5 = nums.partition {|x| x < 5 }
# [[1,2,3,4],[5,6,7,8,9]]

squares = nums.partition {|x| Math.sqrt(x).to_i**2 == x }
# [[1,4,9],[2,3,5,6,7,8]]

使用量词符

nums = [1,3,5,8,9]

# 这些元素有一个偶数吗?
flag1 = nums.any? {|x| x % 2 == 0 }    # true

#这些元素都是偶数吗?
flag2 = nums.all? {|x| x % 2 == 0 }    # false

words得到数组里面最长的那个元素

words = %w[ alpha beta gamma delta epsilon eta theta ]
longest_word=words.inject do |best,w|
  w.length > best.length ? w : best
end
puts longest_word

Range

转化为数组
很简单,to_a方法搞定:
r = 3..12
arr = r.to_a     # [3,4,5,6,7,8,9,10,11,12]

digits = 0..9
digits.include?(5) -> true
digits.min -> 0
digits.max -> 9
digits.reject {|i| i < 5 } -> [5, 6, 7, 8, 9]
digits.each {|digit| dial(digit) } -> 0..9

 ('a'..'z').to_a.each{|i| puts i}   #显示a到z的字符串

r1 = 3..6
r2 = 3...6     #....不包含上线6
r1a, r1b = r1.first, r1.last    # 3, 6
r1c, r1d = r1.begin, r1.end     # 3, 6
r2a, r2b = r2.begin, r2.end     # 3, 6 (注意:不是3和5)

r1 = "7".."9"
r2 = "7".."10"
r1.each {|x| puts x }   # 打印出7,8,9
r2.each {|x| puts x }   # 未打印任何东西
##为什么会出现这样的情况?这是因为这里都是字符串,由于r1中,"7"比"9"小
所以,它是个合理的Range;而表达式r2中,"7"比"10"大,下限大于了上限,就不合理了。

r1 = 23456..34567
x = 14142
y = 31416
r1.include?(x)      # false
r1.include?(y)      # true

迭代器

3.times { print "X " }
1.upto(5) {|i| print i, " " }
99.downto(95) {|i| print i, " " }
50.step(80, 5) {|i| print i, " " }   #50至80之间步长5

数字

?a -> 97 #ASCII值

读取文件

f=File.open("testfile")
f.each{|line| puts line}
f.close

Reading

line=gets   #从键盘输入负值给line
print line  #打印line

Hash

由一个数组来创建hash

array = [2, 3, 4, 5, 6, 7]
hash = Hash[*array]
# hash is now: {2=>3, 4=>5, 6=>7}

合并两个散列

ruby能够使用merge(别名update)方法,来合并两个hash,如果他们中的健有相同的话,一个将会被删除
dict = {"base"=>"foundation", "pedestal"=>"base"}
added = {"base"=>"non-acid", "salt"=>"NaCl"}
new_dict = dict.merge(added)
# {"base"=>"non-acid", "pedestal"=>"base", "salt"=>"NaCl"}

merge还可以使用block来处理,两个健有冲突的hash的合并,
我们下面的代码是假设我们有两个冲突的健的话,我们选择值较小的那个键值对
dict = {"base"=>"foundation", "pedestal"=>"base"}
added = {"base"=>"non-acid", "salt"=>"NaCl"}
new_dict = dict.merge(added) {|key,old,new| old < new ? old : new }
# {"salt"=>"NaCl", "pedestal"=>"base", "base"=>"foundation"}

select(别名finad_all)将会返回所有符合条件的键值对

names.select {|k,v| v=="tucker" }
# [["joe", "tucker"], ["jane", "tucker"]]
names.find_all {|k,v| k.count("r")>0}
# [["mary", "SMITH"], ["fred", "jones"]]

根据条件选择键值对 Hash类混入了Enumerable 模块,因此你能够使用detect (find), select, (find_all), grep, min, max, 和reject 这些方法. detect (别名find)得到一个单独的键值对:

names = {"fred"=>"jones","jane"=>"tucker",
            "joe"=>"tucker","mary"=>"SMITH"}
 # 得到一个tucker
 names.detect {|k,v| v=="tucker" }    # ["joe","tucker"]
 # 得到一个大写的
names.find {|k,v| v==v.upcase }    # ["mary", "SMITH"]

只想把值或者健转换成数组,可以使用keys或者values 你还可以基于一个键序列,来将他们所对应的值转换换成数组

h.keys         # ["a","b"]
h.values       # [1,2]

h = {1=>"one",2=>"two",3=>"three",4=>"four","cinco"=>"five"}
h.values_at(3,"cinco",4)     # ["three","five","four"]
h.values_at(1,3)             # ["one","three"]

你还能使用empty? 方法来测试一个hash是否为空,length来得到一个hash的大小

a.empty?        # false
a.length        # 2

检测一个健或者值是否属于一个hash

我们能够使用has_key?或者它的任意一个别名,include?, key?, 和member?来测试一个key是否属于一个hash
a = {"a"=>1,"b"=>2}
a.has_key? "c"        # false
a.include? "a"        # true
a.key? 2              # false
a.member? "b"         # true

invert

a = {"fred"=>"555-1122","jane"=>"555-7779"}
b = a.invert         #交换hash表中的key和value
b["555-7779"]     # "jane"

注意这里有一个问题,那就是值有可能是重复的,这时如果你使用invert的话,它将会删除掉一个重复的键值对
a = {"fred"=>"555-7779","jane"=>"555-7779"}
b = a.invert
puts b["555-7779"]    # "jane"

迭代hash中的key或value

{"a"=>3,"b"=>2}.each_key do |key|
  print "key = #{key};"      # Prints: key = a; key = b;
end

{"a"=>3,"b"=>2}.each_value do |value|
  print "val = #{value};"    # Prints: val = 3; val = 2;
end

迭代一个hash

我们能够使用each方法来做这个,它还有each_key, each_pair和 each_value方法,其中each_pair是each方法的别名
{"a"=>3,"b"=>2}.each do |key, val|
  print val, " from ", key, "; "    # 3 from a; 2 from b;
end
{"a"=>3,"b"=>2}.each{|key,val|puts "#{val} from #{key}"}

删除的话我们能够使用 clear, delete, delete_if, reject, reject!, 和shift 这些方法都能做到。 clear 将会把一个hash清空.shift则将会删除掉最前面的一个键值对

存取或者加一个键值对

hash也有像数组一样的[]和[]=方法,还有一个store,它是[]=方法的别名
a = {}
a["flat"] = 3        # {"flat"=>3}
a.[]=("curved",2)    # {"flat"=>3,"curved"=>2}
a.store("angled",5)  # {"flat"=>3,"curved"=>2,"angled"=>5}

puts a
histogram = Hash.new() #新建一个Hash表
histogram['key1'] -> 0
histogram['key1'] = histogram['key1'] + 1
histogram['key1'] -> 1

histogram.default = "hello"  #没有定义的key会返回hello

Array

数组的交叉

a = [1, 2, 3, 4]
b = ["a", "b", "c", "d"]
c = a.zip(b)
# c is now [[1,"a"], [2,"b"], [3,"c"], [4,"d"]]
# Use flatten if you want to eliminate the nesting
d = c.flatten
# d is now [1, "a", 2, "b", 3, "c", 4, "d"]

uniq

移除掉重复的元素
breakfast = %w[spam spam eggs ham eggs spam]
lunch = breakfast.uniq   # ["spam","eggs","ham"]
breakfast.uniq!          # breakfast has changed now

join

将数组转换成字符串
been_there = ["Veni", "vidi", "vici."]
journal = been_there.join(", ")        # "Veni, vidi, vici."
journal.class                          # String

letters = ["Phi","Mu","Alpha"]
musicians = letters.join(" ")          # "Phi Mu Alpha"

people = ["Bob","Carol","Ted","Alice"]
movie = people * " and "
# movie is now "Bob and Carol and Ted and Alice"

each_with_index 方法的block将会多出一个index参数

x = ["alpha", "beta", "gamma"]
x.each_with_index do |x,i|
  puts "Element #{i} is #{x}"
end

reverse_each

words = %w(Son I am able she said)
str = ""
words.reverse_each { |w| str += "#{w} "}
# str is now "said she able am I Son "

clear方法将会删除一个数组中的所有元素。

shift和pop方法,也能删除数组中的元素

x = [1, 2, 3, 4, 5]
x.pop                   # Delete the last element
# x is now [1, 2, 3, 4]
x.shift                 # Delete the first element
# x is now [2, 3, 4]

delete

我们还能使用delete方法来删除一个指定的元素
b = %w(spam spam bacon spam eggs ham spam)
b.delete("spam")            # Returns "spam"
# b is now ["bacon", "eggs", "ham"]
b.delete("caviar")          # Returns nil

delete还能跟上一个block,block的意思就是如果找不到那个元素就会返回block
c = ["alpha", "beta", "gamma", "delta"]
c.delete("delta") { "Nonexistent" }
# Returns "delta" (block is never evaulated)
c.delete("omega") { "Nonexistent" }
# Returns "Nonexistent"

delete_at

我们能够使用delete_at方法来删除一个指定位置的元素
a = [10, 12, 14, 16, 18]
a.delete_at(3)              # 删除 第三个元素(从0开始) Returns 16
# a is now [10, 12, 14, 18]
a.delete_at(9)              # Returns nil (out of range)

compact

a = [1, 2, nil, 3, nil, 4, 5]
b = a.compact     # [1, 2, 3, 4, 5]     #除去数组中的nil
a.compact!        # a is now [1, 2, 3, 4, 5]

rand

将一个数组随机显示,也就是打乱掉
我们可以使用kernel的rand方法
x = [1, 2, 3, 4, 5]
x.sort_by{rand} #[2, 3, 1, 4, 5]

array并没有定义异或操作,可是我们能够自己定义异或操作

class Array

  def ^(other)
    (self | other) - (self & other)
  end

end

x = [1, 2, 3, 4, 5]
y = [3, 4, 5, 6, 7]
z = x ^ y            # [1, 2, 6, 7]

grep

grep方法调用===方法来匹配数组中的每一个元素与他自己所带的参数
由于是使用===方法,因此grep方法的参数不需要是正则表达式
a = %w[January February March April May]
a.grep(/ary/)      # ["January, "February"]
b = [1, 20, 5, 7, 13, 33, 15, 28]
b.grep(12..24)     # [20, 13, 15]

如果使用它的block版本的话,那就更灵活,这样可以再次处理所匹配的元素
# Continuing above example...
# Let's store the string lengths
a.grep(/ary/) {|m| m.length}     # [7, 8]
# Let's square each value
b.grep(12..24) {|n| n*n}         # {400, 169, 225}

sort

words = %w(the quick brown fox)
list = words.sort  # ["brown", "fox", "quick", "the"]  #数组内部排序函数
puts list.to_s
# Or sort in place:
words.sort!        # ["brown", "fox", "quick", "the"]

sort方法假设数组里面没一个元素都是可比较的
因此比如[1, 2, "tHRee", 4]这样的数组,进行排序的话,就会报错.

我们还可以使用一种更灵活的排序方式,那就是使用sort的block版本
a = [1, 2, "three", "four", 5, 6]
b = a.sort {|x,y| x.to_s <=> y.to_s}  #x,y分别是每次传进来的两个元素.
# b is now [1, 2, 5, 6, "four", "three"]
x = [1, 4, 3, 5, 2]
y = x.sort {|a,b| b <=> a}    # [5, 4, 3, 2, 1]

当我们想要根据很多key来排序的话,我们使用sort方法,就显得非常麻烦
这个时候我们能够使用Enumerable 模块的sort_by方法
words=[1,2,"3"]
puts words.sort       #错误不能排序
puts lists =words.sort_by{|item| item.to_s}   # 1 2 3

shift

char=[a,b,b,c].shift   #删除数组中的第一个字符
puts char  # a

想得到数组中某几个元素组成的数组,你可以使用values_at方法

x = [10, 20, 30, 40, 50, 60]
y = x.values_at(0, 1, 4)        # [10, 20, 50]
z = x.values_at(0..2,5)         # [10, 20, 30, 60]
[1,3,5,7,9].find{|v| v*v < 30 }   #返回满足条件的第一个值
x.detect {|e| e % 2 == 0 }         # 8  功能与find相同

如果我们想得到这个数组中所有的偶数
这是就该使用find_all方法,而select和find_all方法是同意的
# Continuing the above example...
x.find {|e| e % 2 == 0}            # 8
x.find_all {|e| e % 2 == 0}        # [8, 12, 4, 30]
x.select {|e| e % 2 == 0}          # [8, 12, 4, 30]

reject方法和select完全相反,看名字就知道了,它是选择不符合条件的
c = [5, 8, 12, 9, 4, 30]
d = c.reject {|e| e % 2 == 0}      # [5, 9]
puts c.reject! {|e| e % 3 == 0}    # c is now [5, 8, 4]

["H", "A", "L"].collect {|x| x.succ }  #输下当前字符的下一字符

[1,3,5,7,9].each{|i| puts i }   #遍历数组

[1,3,5,7].inject {|sum, element| sum+element}                    #数组求和
[1,3,5,7].inject {|product, element| product*element}        #数组求积

a=Array.new  #新建一个数组

a = [ 'ant', 'bee', 'cat', 'dog', 'elk' ]
a[0] -> "ant"
a[3] -> "dog"

# this is the same:
a = %w{ ant bee cat dog elk }
a[0] -> "ant"
a[3] -> "dog"

y = [1, 2, nil, nil, 3, 4]
c = y.size                 # 6
d = y.length               # 6
e = y.nitems               # 4   统计数组长度不包含nil

变量

全局变量 用$开头 实例变量 用@开头 类变量 用@@ 开头

person = "Tim"
person.id -> 936870
person.class -> String
person -> "Tim"

#{..} → 可以在引号中引用变量值或

def say_goodnight(name)
result = "Good night, #{name.capitalize}" #.capitalize输出字符串首字母大写
return result
end
puts say_goodnight('uncle')

输出结果:
Good night, Uncle

String

squeeze

我们可以使用squeeze 方法来一处重复的字符

s1 = "bookkeeper"
puts s2 = s1.squeeze         # "bokeper"
s3 = "Hello..."
puts s4 = s3.squeeze         # "Helo."
#If a parameter is specified, only those characters will be squeezed.
puts s5 = s3.squeeze(".")    # "Hello."

将一个字符串按照单词进行反转,那么你就会用到split方法和,数组的reverse方法

phrase = "Now here's a sentence"
puts phrase.split(" ").reverse.join(" ")
# "sentence a here's Now"

strip

strip将会删除掉字符串的开头和结尾的空格
sss="a d c "
puts sss.strip  => abc

如果你只想从字符串的开头或者结尾的空格,那么可以使用lstrip或者rstrip
str = "  abc  "
s2 = str.lstrip       # "abc  "
s3 = str.rstrip       # "  abc"

chop

chop方法将会删除最后一个字符,返回新的string。如果字符是以\r\n结束,则两个字符都会被删除

str = "abcxyz"
s1 = str.chop           # "abcxy"
str2="abc\r\n"
s2=str2.chop  #abc

chomp

str = "abcxyz"
puts s1 = str.chomp #abcxyz
str2 = "123\n"
puts s2=str2.chomp   #123
str1 = "abcxyz"
str2 = "abcxyz"
puts s1 = str1.chomp("yz")   # "abcx"
puts s2 = str2.chomp("x")    # "abcxyz"   #只匹配结尾的词

unpack

puts  "E".unpack("c")    #69   输出一个字符串的asc码值

«

puts  "a"<<111    <<符号或者chr来把一个asc转换为字符串:
puts  111.chr

scan

"hello world".scan(/./){|s| print s}  #扫描匹配的字符串并打印

casecmp

n4 = "ABC".casecmp("abc")   # 0 功能同<=>忽略大小写

puts

str="bobo"
puts str.ljust(8,"++")    #左对齐其余用++补齐
puts str.rjust(8,"++")    #右对齐其余用++补齐
"Seconds/day: #{24*60*60}" -> Seconds/day: 86400
"#{'Ho! '*3}Merry Christmas!" -> Ho! Ho! Ho! Merry Christmas!
"This is line #$." -> This is line 3         # #?显示程序块中语句所在的行号

each_byte

str="bobo"
str.each_byte{|byte| puts byte.chr}
结果:
b
o
b
o

dup

person1 = "Tim"
person2 = person1.dup   #同.new功能相同也可以用person2=person1
person1[0] = "J"
person1 -> "Jim"
person2 -> "Tim"

freeze

person1 = "Tim"
person2 = person1
person1.freeze   # 字符串不可变
person2[0] = "J"
结果:
prog.rb:4:in `[]=': can't modify frozen string (TypeError)
from prog.rb:4

index & rindex

index方法返回指定的子字符串,正则表达式或者字符的起始位置(如果有多个匹配的只返回第一个匹配的起始位置)
没有发现的话返回nil,而rindex则是从string的右边(也就是结束处)开始查找,不过返回的值却是从左边数起的:

str = "Albert Einstein"
puts pos1 = str.index(?E)        # 7
puts pos1 = str.index(69)        # 7
puts pos2 = str.index("bert")    # 2
puts pos3 = str.index(/in/)      # 8
puts pos4 = str.index(?e)        # nil
puts pos5 = str.index("bart")    # nil
puts pos6 = str.index(/wein/)    # nil

正侧表达式

sub或者gsub方法来进行替换,他们两个方法第一个参数都是接受正则表达式。
其中,sub方法替换掉第一个匹配的地方,而gsub方法替换掉全部匹配的地方:

s1 = "spam, spam, and eggs"
s2 = s1.sub(/spam/,"bacon")               # "bacon, spam, and eggs"

s3 = s2.sub(/(\w+), (\w+),/,'\2, \1,')    # "spam, bacon, and eggs"

s4 = "Don't forget the spam."
s5 = s4.sub(/spam/) { |m| m.reverse }     # "Don't forget the maps."  把匹配部分的单词反转
s5 = "alfalfa abracadabra"
s6 = s5.gsub(/a[bl]/,"xx")     # "xxfxxfa xxracadxxra"
s5.gsub(/[lfdbr]/) { |m| m.upcase + "-" }
# s5 is now "aL-F-aL-F-a aB-R-acaD-aB-R-a"

String类常用函数表

函数名称 说明 示例
* 将字符串拷贝N次 “ha”*4 » “hahahaha”
+ 连接字符串 “yes”+“no” » “yesno”
« 连接字符串 “yes”+“no” » “yesno”
concat 连接字符串 “yes”+“no” » “yesno”
比较字符串,返回值: 大于=-1 “Ab” ⇔ “ab” » -1
等于=0 “ab” ⇔ “ab” » 0
小于=1 “ab” ⇔ “Ab” » 1
== 或 ===判断两个对象是否相等 “1” == “1” » true , “1” == 1 » flase
=~匹配正则表达式 “abc123abc” =~ /\d/ » 3
[ ] 或 slice返回字符串的某一范围内的值 “abc”[0,2] » “ab”, “hello”[/llo/] » “llo”, “abc”.slice(0,2) » “ab”
[]=替换字符串的某一范围内的值a=“hello word” → a[1,2]=“OO” → puts a »“hOOlo word”
capitalize,capitalize!把字符串的首字母大写,其他字母小写“hi,Ruby”.capitalize » “Hi,ruby”
chomp,chomp!删除字符串后的空白字符“string”r”n”.chomp »“string”
chop删除最后一个字符“string”.chop » “strin”
count返回该字符串中含的字符个数a = “hello world” → a.count “lo” » 5 #(l出现 3次,o出现 2次)

基础

ruby打印输出命令

puts 带换行符输出

priint 不带换行符输出

ruby中区间表示

1..5表示1,2,3,4,5

1...5表示1,2,3,4
/var/lib/openshift/bccd8eac1968476490eaee9ced33c7bf/app-root/runtime/repo/php/data/pages/ruby.txt · 最后更改: 2012/09/07 09:21 (外部编辑)
到顶部
CC Attribution-Noncommercial-Share Alike 3.0 Unported
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0