代码翻译,从Python到Ruby

2 投票
2 回答
3619 浏览
提问于 2025-04-15 18:25

我想把一些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 个回答

1

这段代码能满足你的需求:

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/

2

我们一个一个方法来看,先从 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

如果你需要更多关于以上内容的细节,随时告诉我。

撰写回答