代码翻译,从Python到Ruby
我想把一些Python的代码转换成Ruby,这个想法来自于Thomas Guest写的一篇很棒的文章,链接在这里:http://wordaligned.org/articles/drawing-chess-positions
(注意:我真的是个Python新手)
下面是原始的Python代码:
def expand_blanks(fen):
'''Expand the digits in an FEN string into spaces
>>> expand_blanks("rk4q3")
'rk q '
'''
def expand(match):
return ' ' * int(match.group(0))
return re.compile(r'\d').sub(expand, fen)
def outer_join(sep, ss):
'''Like string.join, but encloses the result with outer separators.
Example:
>>> outer_join('|', ['1', '2', '3'])
'|1|2|3|'
'''
return '%s%s%s' % (sep, sep.join(ss), sep)
def ascii_draw_chess_position(fen):
'''Returns an ASCII picture of pieces on a chessboard.'''
pieces = expand_blanks(fen).replace('/', '')
divider = '+-+-+-+-+-+-+-+-+\n'
rows = ((outer_join('|', pieces[r: r + 8]) + '\n')
for r in range(0, 8 * 8, 8))
return outer_join(divider, rows)
使用示例:
>>> fen = "r2q1rk1/pp2ppbp/1np2np1/2Q3B1/3PP1b1/2N2N2/PP3PPP/3RKB1R"
>>> print ascii_draw_chess_position(fen)
+-+-+-+-+-+-+-+-+
|r| | |q| |r|k| |
+-+-+-+-+-+-+-+-+
|p|p| | |p|p|b|p|
+-+-+-+-+-+-+-+-+
| |n|p| | |n|p| |
+-+-+-+-+-+-+-+-+
| | |Q| | | |B| |
+-+-+-+-+-+-+-+-+
| | | |P|P| |b| |
+-+-+-+-+-+-+-+-+
| | |N| | |N| | |
+-+-+-+-+-+-+-+-+
|P|P| | | |P|P|P|
+-+-+-+-+-+-+-+-+
| | | |R|K|B| |R|
+-+-+-+-+-+-+-+-+
我一直在尝试做一些修改,把每一行转换成Ruby... 我在想这样开始是否不好 :s 不过我还是决定发布出来:
def expand_blanks(fen)
def expand(match)
return ' ' * int(match.group(0))
end
# bugged:
re.compile(r'\d').sub(expand, fen)
end
def outer_join(sep, ss)
sep + sep.join(ss) + sep
end
def ascii_draw_chess_position(fen)
pieces = expand_blanks(fen).replace('/', '')
puts pieces.class
divider = "+-+-+-+-+-+-+-+-+\n"
# bugged lines:
rows = ((outer_join('|', pieces[r, r + 8]) + '\n')
for r in range(0, 8 * 8, 8))
return outer_join(divider, rows)
end
end
fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR"
puts ascii_draw_chess_position(fen)
如果你看到我有可以改进的地方,能告诉我就太好了。谢谢大家。
2 个回答
这段代码能满足你的需求:
def expand(match)
' ' * match.to_i
end
def expand_blanks(fen)
fen.gsub(/\d/) {|d| expand d}
end
def outer_join(sep, ss)
sep + ss.join(sep) + sep
end
def ascii_draw_chess_position(fen)
pieces = expand_blanks(fen).gsub('/', '')
divider = "+-+-+-+-+-+-+-+-+\n"
rows = (0...8).collect do |i|
row = pieces[i*8...(i+1)*8].split('')
outer_join("|",row) + "\n"
end
puts outer_join(divider, rows)
end
如果你对这里的代码有不明白的地方,随时告诉我。不过在问之前,最好先去看看Ruby文档里的方法说明。
如果你想了解Ruby和Python之间的区别,可以参考这里:https://stackoverflow.com/questions/234721/what-are-the-biggest-differences-between-python-and-ruby-from-a-philosophical-per,或者这里:http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-python/。如果你想看一些好的例子,可以访问http://ruby.brian-amberg.de/editierdistanz/。
我们一个一个方法来看,先从 outer_join
开始。
在 Python 中,join
是字符串上的一个方法,它可以把一个序列中的元素用指定的字符串连接起来。例如,'|'.join(['p', 'p', 'p'])
会把列表中的 'p' 用 '|' 连接起来。
而在 Ruby 中,join
是数组上的一个方法,它接受一个分隔符作为参数。例如,['p', 'p', 'p'].join('|')
也会得到类似的效果。
所以 Ruby 版本的 outer_join
代码会是:
def outer_join(sep, ss):
sep + ss.join(sep) + sep
end
接下来我们看看 expand_blanks
,这个方法的目的是把数字替换成相应数量的空格。在 Ruby 中,可以用 gsub
方法来替换字符串中所有匹配的部分。gsub
可以带一个块,这个块会接收每个匹配的子字符串,并返回要替换成的字符串。所以 Ruby 的代码会是:
def expand_blanks(fen)
fen.gsub(/\d/) { |match| ' ' * match.to_i }
end
最后在 ascii_draw_chess_position
中,我们可以再次使用 gsub
,它相当于 Python 的 replace
方法。同时,我们可以用 Ruby 的 map
函数来替代 Python 中用列表推导式实现的功能,代码如下:
def ascii_draw_chess_position(fen)
pieces = expand_blanks(fen).gsub('/', '')
divider = "+-+-+-+-+-+-+-+-+\n"
rows = (0...8).map do |i|
row = pieces[i * 8...(i + 1) * 8].split('')
outer_join("|",row) + "\n"
end
puts outer_join(divider, rows)
end
如果你需要更多关于以上内容的细节,随时告诉我。