《Ruby基础教程》第四部分提取笔记

散列类

  1. 新建hash:

    • a = {} a = {键: 值}
    • a = Hash.new(x) (这里可以设置一个默认值)。
  2. 值的获取与设定

    • fetch & store 一个用来取一个用来存,基本和a["s"]的作法一样,但:

      用下面两个方法可以

      • 设默认值
      • 添加block
      a.store("s1", "Ruby")
      a.fetch("s2", "undef")     #=> "undef"   (找不到,所以默认值)
      a.fetch("s2"){String.new}  #=> ""    (这里还可以用block)
      
  3. hash的迭代器。

    数组形式 迭代器形式
    keys each_key{|键| …… }
    Values each_value{|值| …… }
    to_a each{|键,值| …… }
    each{|数组| …… }
  4. hash的默认值。好处:取不存在的值时,不至于发生错误

    • 创建hash时指定默认值:

      h = Hash.new(1)
      h["a"] = 10
      h["a"]          #=> 10
      h["b"]          #=> 1
      
    • 创建hash时增加一个block:

      h = Hash.new do |hash,key|
        hash[key] = key.upcase
      end
      h ["a"] = "b"
      p h["a"]      #=> "b"
      p h["b"]      #=> "B"
      p h["c"]      #=> "C"  当找不到这个值时,就会自动去执行这个block
      
    • 用fetch方法指定默认值:

      h = Hash.new do |hash.key|
       hash[key] = key.upcase
      end
      p h.fetch("x", "(undef)")      #=> "(undef)"
      同时两个默认值的方法,fetch的优级级会高
      
  5. 判断是否为某个Hash的 or

      • h.key?(key)
      • h.has_key?(key)
      • h.include?(key)
      • h.member?(key)
      • h.value?(value)
      • h.has_value?(value)
  6. 查看Hash的大小

    • h.size & h.length

      h = {"a" => "b", "c" => "d"}
      h.size      #=> 2
      
    • h.empty?

  7. 删除值:

    • h.delete(key)

    • h.delete_if{|key, val| … }

    • h.reject!{|key, val| … }

      当不符合时,delete_if会返回原来的Hash,reject!会返回一个nil

  8. 初始化散列

    • h.clear 清空使用过的散列

      那这个东西和h = Hash.new 有什么区别呢?在引用的时候要注意下,请看图:

      image

    • 我忘记了一个超级方便的排序方法:sort
      PS:比起之学VB时的什么泡沫排序法之类的,这里简直不能太好!

正在表达式(Regexp类)

  1. 正则表达式的创建:

    re = Regexp.new("Ruby")      #=> /Ruby/
    
    • %r(模式)
    • %r<模式>
    • %r|模式|
    • %r!模式!
  2. 判断某个字符串是否匹配:正则表达式 =~ 字符串

    • 匹配:返回匹配的起始位置

    • 不匹配:返回nil

      还可以:用!~来颠倒结果。

    • 进一步应用:

      if 正则表达式 =~ 字符串
        匹配时的处理
      else
        不匹配时的处理
      end
      
  3. 匹配行首与行尾:

    ^, $分别表示匹配行首与行尾:

    像这样的特殊字符称为:元字符。

    \A,\z分别表示匹配字符串头与尾:

    \z \Z 两者的区别

    p "abc\n".gsub(/\z/, "!") => "abc\n!" 
    p "abc\n".gsub(/\Z/, "!") => "abc!\n!"
    

    :大写的\Z,如果最后一个是换行符,则会同时匹配换行符与前一个字符。

  4. 匹配某一个字符:

    • [AB] :匹配A 或B
    • [ABC] :匹配A,B,C中的一个
    • [012ABC] :匹配0,1,2,A,B,C中的一个
    • [A-Z] :匹配A~Z中的一个
    • [ABC][BC] : 匹配一个两位数,第一个数为A,B,C中的一个,第二位数为B,C中的一个。
    • [A_-] :匹配A _ - 中的一个。
    • [^ABC] :匹配除A,B,C外的任意一位数。
    • . :万能通配符,相当于五笔中的z
  5. 反斜杠模式

    • \s : 匹配空格,制表符, 换行符,换页符

    • \d :匹配0到9的数字。

    • \w :匹配英文字与数字。

    • \A :匹配字符串的开头。

    • \z :匹配字符串的末尾。

    • \ :后面如果跟着:^ $ [ 等字符时,可以为这些字符转义再匹配。如:

      模式 字符串 匹配部分
      /ABC[/ "ABC[" "▶ ABC[ ◀"
      /^ABC/ "ABC" (不匹配)
      /^ABC/ "012^ABC" "012▶^ABC ◀"
  6. 重复模式:(单个字符)

    • * :重复0次以上。可以重复很多次也可以直接没有
    • + :重复1次以上。至少有一次以上
    • ? :重复0次或1次。可有可无不重复,前后的匹配还是要的!
  7. 最短匹配:

    • 上面6中和重复匹配会最可能匹配更多的字符。

    • 最短匹配:加上一个? ,在第一次匹配时就停止,匹配最短的字符。

      也叫贪婪匹配与懒惰匹配。

  8. 使用()来重复匹配多个字符。

    模式 字符串 匹配部分
    /^(ABC)*$/ "ABC" "▶ABC ◀"
    /^(ABC)*$/ "" "▶◀"
    /^(ABC)*$/ "ABCABC" "▶ABCABC ◀"
    /^(ABC)*$/ "ABCABCAB" (不匹配)
  9. 使用|来多一个匹配选项,可以多选一,也可以全中。

    模式 字符串 匹配部分
    /^(ABC|DEF)$/ "ABC" "▶ABC ◀"
    /^(ABC|DEF)$/ "DEF" "▶DEF ◀"
    /^(ABC|DEF)$/ "AB" (不匹配)
  10. 使用quote方法来转义所有表达式所有字符:

 re1 = Regexp.new("abc*def")
 re2 = Regexp.new(Regexp.quote("abc*def"))
 p (re1 =~ "abc*def") #=> nil
 p (re2 =~ "abc*def") #=> 0
  1. 正则表达式的一些选项:

    形式:/ … / im

    • i :忽略英文有大小写
    • x :忽略正则表达式中的空白字符以及 # 后面的字符的选项。指定这个选项后,我们就可以使用 # 在正则表达式中写注释了。
    • m :使用后可以:用.匹配换行符了。
  2. 捕获:

    • 查看匹配的部分是什么字符串:以()的形式

      /(.)(.)(.)/ =~ "abc" 
      first = $1
      second = $2
      third = $3
      p first      #=> "a"
      p second     #=> "b"
      p third      #=> "c"
      
    • 如果是有重复的匹配只会捕获最后一次的字符,如果此时我们想忽略它的捕获,可以这样:以(?:)开头就可以忽略捕获。

      /(.)(\d\d)+(.)/ =~ "123456"
      p$1 #=> "1"
      p$2 #=> "45"
      p$3 #=> "6"
      /(.)(?:\d\d)+(.)/ =~ "123456" 
      p $1 #=> "1"
      p $2 #=> "6"
      
    • 另外一种形式:

      /C./ =~ "ABCDEF"
      p $`   #=> "AB"
      p $&   #=> "CD"
      p $'   #=> "EF"
        这三种可以捕获整个匹配过程的字符
      
  3. sub方法与gsub方法:带block

    str = "abracatabra"
    nstr = str.sub(/.a/) do |matched|
      '<'+matched.upcase+'>' 
    end
    p nstr #=> "abcatabra"
    nstr = str.gsub(/.a/) do |matched|
      '<'+matched.upcase+'>'
    end 
    p nstr #=> "abb"
    

    可以带block,然后把匹配的部分传入block,最后block处理后的结果置换匹配的字符串。

  4. 直接返回的字符串数组:scan方法

    p "abracatabra".scan(/.a/) #=> ["ra", "ca", "ta", "ra"]
    

这是纠正一点:转义符号增加的顺序:

 /http:\/\// =~ "http://baidu.com"   
 $&    #=> "http://"        

纠正:\+要转义的符号 这才是正确的格式。

章节:IO类

这一章节主要对文件内容的操作。暂时不会用到,理解起来也费劲。

章节:File类与Dir类

这一章节主要是对文件夹的操作。暂时不会用到,记起来也很费劲。

章节:Encoding类

这一章节主要是编码类的讲解。暂时不会用到,要用到时再来查看。

第20章 Time类与Date类

  1. 获取当前时间:

    • Time.new
    • Time.now

    时间相关的方法:

    方法名 意义
    year
    month
    day
    hour
    min
    sec
    usec 秒以下的位数(以毫秒为单位)
    to_i 从 1970 年 1 月 1 日到当前时间的秒数
    wday 一周中的第几天(0 表示星期天)
    mday 一个月中的第几天(与 day 方法一样)
    yday 一年中的第几天(1 表示 1 月 1 日)
    zone 时区(JST 等)
  2. 指定特定时间:

    t = Time.mktime(2017,7,25,16.59,40)
    #=> 2017-07-25 16:40:00 +0800
    
  3. 时间的比较:

    • < > - 等,平常的计算比较方法都可以用啦。
  4. 时间的计算:默认直接计算秒数:

    t = Time.now
    p t #=> 2013-03-30 03:11:44 +0900 t2=t+60*60*24 #=>增加24小时的秒数
    p t2 #=> 2013-03-31 03:11:44 +0900
    
  5. 时间输出的格式:

    • t.strftime(format)
    • t.to_s
    格式 意义与范围
    %A 星期的名称(Sunday 、 Monday ......)
    %a 星期的缩写名称(Sun 、 Mon ......)
    %B 月份的名称(January 、 February ......)
    %b 月份的缩写(Jan 、 Feb ......)
    %c 日期与时间
    %d 日(01 ~ 31)
    %H 24 小时制(00 ~ 23)
    %I 12 小时制(01 ~ 12)
    %j 一年中的天(001 ~ 366)
    %M 分(00 ~ 59)
    %m 表示月的数字(01 ~ 12)
    %p 上午或下午(AM、PM)
    %S 秒(00 ~ 60)
    %U 表示周的数字。以星期天为一周的开始(00 ~ 53)
    %W 表示周的数字。以星期一为一周的开始(00 ~ 53)
    %w 表示星期的数字。0 表示星期天(0 ~ 6)
    %X 时间
    %x 日期
    %Y 表示西历的数字
    %y 西历的后两位(00 ~ 99)
    %Z 时区( JST 等)
    %z 时区(+0900 等)
    %% 原封不动地输出 %

    示例:

    t = Time.now.strftime("%Y-%m-%d")
    #=> "2017-7-25"
    
    另外两个冷门的格式:(需要引用time类)
    • t.rfc2822
    • t.iso8601f
    require "time"
    t = Time.now
    p t.rfc2822      #=> "Tue, 25 Jul 2017 17:19:00 +0800"
    p t.iso8601      #=> "2017-07-25T17:19:42+08:00"
    
  6. 本地时间与国际时间的切换:

    • t.utc
    • t.localtime
    t = Time.now
    p t            #=>  2017-07-25 17:21:35 +0800
    t.utc          #=>  2017-07-25 09:21:35 UTC
    t.localtime    #=>  2017-07-25 17:21:35 +0800
    
  7. 从字符串中获取时间:

    • Time.parse(str)

      require "time"
      
      p Time.parse("2017-7-25")   #=> 2017-07-25 00:00:00 +0800
      
  8. 日期的获取:Date类,适合只需日期不需时间的操作。

    • Date.today

    • 计算:直接加减默认计算天数

    • 同样也有各种方法:

      d = Date.today
      p d.year pd.month pd.day
      p d.wday p d.mday pd.yday
      # 年 => 2017
      #月 => 7
      #日 => 25
      # 一周中的第几天(0 表示星期天)
      # 一个月中的第几天(与 day 方法一样) => 30 #一年中的第几天(1表示 1月 1日) =>206
      
    • 用指定日期生成Date对象:

      d = Date.new(2017,7,25)
      puts d     #=> 2017-7-25
      

      还可以用-1 -2 表示末尾的第几天:

      d = Date.new(2017,7,-1)   #=> 2017-7-31   7月月尾
      d = Date.new(2017,7,-2)   #=> 2017-7-30   7月月尾前一天
      
  9. Date类的运算:

    • 正常的加减,默认会以天数为单位计算
    • >> << 会以月份为单位进行运算。
  10. Date类的格式:

  • 与前面的Time类一致。
  1. 从字符串中获取Date类:
    • 和Time类一致: Date.parse(str)

Proc类

  1. 什么是proc类,

    把block块变成一个对象,这个对象所属的类就是Proc类。这样可以方便我们在后面的调用。

  2. 创建方法:

    • Proc.new(…)
    • proc{}
  3. 调用方法:

    • 利用Proc#call方法

    • 利用Proc[]方法

      sayhello = Proc.new do |name|
        puts "Hello, #{name}."
      end
      
      sayhello.call("World")    #=> Hello, World.
      sayhello["World"]         #=> Hello, World.
      
  4. 另一种写法:lambda

    lambda 还有另外一种写法:-> (块变量){处理}

    prc1 = Proc.new do |a, b, c|
      p [a, b, c]
    end
    prc1.call(1,2)     #=> [1, 2, nil]
    
    prc2 = lambda do |a, b, c|
      p [a, b, c]
    end
    prc2.call(1,2)     #=> 错误 (ArgumentError)
    

    lambda proc 两者的区别:

    • lambda的参数数量要对应否则会出错,proc的参数数量则没有那么严格。
    • lambda可以使用return将值从块中返回。
  5. proc类可以接收块

  6. proc的特征:

    具有闭包的特征。 闭包:将处理内容、变量等环境同时进行保存的对象,在编程语言中称为闭包(closure)。

  7. proc的实例方法:

    • prc.call(args,…)
    • prc[args, … ]
    • prc.yield(args, … )
    • prc.(args, … )
    • prc === arg
    prc = Proc.new{|a, b| a + b}
    p prc.call(1, 2)    #=> 3
    p prc[3, 4]         #=> 7
    p prc.yield(5, 6)   #=> 11
    p prc.(7, 8)        #=> 15
    p prc === [9, 10]   #=> 19
    
    fizz = proc{|n| n % 3 == 0 }
    buzz = proc{|n| n % 5 == 0 }
    fizzbuzz = proc{|n| n % 3 == 0 && n % 5 == 0} 
    (1..100).each do |i|
      case i
        when fizzbuzz then puts "Fizz Buzz" 
        when fizz then puts "Fizz"
        when buzz then puts "Buzz"
      else
        puts i
      end
    end
    
    • prc.arity : 返回块变量的个数。
    • prc.parameters
      image
    • prc.lambda? :判断是否通过lambda定义的方法。
    • prc.source_location: 返回值为[代码文件名,行编号]

你可能感兴趣的:(《Ruby基础教程》第四部分提取笔记)