Ruby 并行赋值的使用场景

hooopo · 2013年11月14日 · 最后由 bhuztez 回复于 2013年12月12日 · 4426 次阅读

以前写 CSV 最讨厌的就是把每一行数据和变量名对应起来,特别是遇到 CSV 文件的列数非常多的情况。发现一个小 Tip,用并行赋值的写法处理起来非常方便....

之前写法:

CSV.foreach("csv_path") do |row|
  title = row[0]
  desc = row[1]
  name = row[2]
  # handle title, desc name
end

并行赋值:

CSV.foreach("csv_path") do |row|
  title, desc, name, * = row
  # handle title, desc, name
end

并行赋值还有哪些应用?

这该叫 destructuring 吧

最简单的,变量值互换

a,b = b,a

很常见的写法啊 foo, bar, biz = [:foo, :bar, :biz]

想起最开始学JAVA的时候写CRUD那几个方法。那个表有20多个字段,每次要修改的时候都要去 insert 后面查问号 =.=

只要右边的对象有to_ary方法就可以

这个叫 poor man's pattern matching 吧

a,b,c,d = *0...4

#3 楼 @zgm 不,,我觉得这种两个三个变量的赋值这么写没什么优势。当你已经写好了三个变量的并行赋值,你想加第四个的时候就麻烦了,要多移动好多光标..

所以 我觉得 csv 这里用并行赋值是最佳的场景。

CSV.foreach("csv_path") do |(title, desc, name, *rest)|
  # handle title, desc, name
end

#2 楼 @neo 这应该也算一种合适的场景。

_, date, urlname, _ = *filename.match(/\A#{tmp_path}\/_posts\/(\d+-\d+-\d+)-(.+)(\.[^.]+)\z/)

解析 jekyll post 的文件名。

#10 楼 @hooopo 你需要的是一门原生支持 pattern matching 的语言,比如,badmatch https://github.com/bhuztez/badmatch

#14 楼 @bhuztez 你这只是一个 README 啊!

#12 楼 @Rei

/\A#{tmp_path}\/_posts\/(?<date>\d+-\d+-\d+)-(?<urlname>.+)(\.[^.]+)\z/ =~ filename

然后 date 和 urlname 都在局部变量里了

#14 楼 @bhuztez 其实 ruby 的 case 语句已经很接近了

case [x, y, z]
when [x, x, x] then :equilateral
when [x, x, z], [x, z, z] then :isosceles
else :scalene
end

Array 加个解构匹配方法就更差不多了

class Array
  def === other
    size == other.size and
    zip(other).all? do |e, oe|
      e === oe
    end
  end
end

foo = 3
case [foo, "bar"]
when [Integer, "bar"] then puts "matched"
end

#17 楼 @luikore

irb(main):001:0> case [1,2,3] when [x,y,z] then puts "ok" end
NameError: undefined local variable or method `x' for main:Object
    from (irb):1
    from /usr/bin/irb:12:in `<main>'

#18 楼 @bhuztez ruby 有并行赋值,有匹配。但只有正则才有 "一句话写完匹配和并行赋值" 的构造

#18 楼 @bhuztez x,y,z 没赋值?

@hooopo 被你坑了 ... 不行啊

#24 楼 @hooopo 改成*就好了 ...

#9 楼 @luikore haha,看到楼主的帖子就知道你要回复这个了

#15 楼 @hooopo 感觉语法有问题,试了一下的确不行,还得再改改,现在的写法不能被 LALR 解析 ...

需要 登录 后方可回复, 如果你还没有账号请 注册新账号