【问题标题】:How do I implement Common Lisp's mapcar in Ruby?如何在 Ruby 中实现 Common Lisp 的 mapcar?
【发布时间】:2013-08-10 08:09:51
【问题描述】:

我想在 Ruby 中实现 Lisp 的 mapcar

如意语法:

mul = -> (*args) { args.reduce(:*) }

mapcar(mul, [1,2,3], [4,5], [6]) would yield [24, nil, nil].

这是我能想到的解决方案:

arrs[0].zip(arrs[1], arrs[2]) => [[1, 4, 6], [2, 5, nil], [3, nil, nil]]

那么我可以:

[[1, 4, 6], [2, 5, nil], [3, nil, nil]].map do |e| 
  e.reduce(&mul) unless e.include?(nil)
end

=> [24, nil, nil]

但我被困在zip 部分。如果输入为[[1], [1,2], [1,2,3], [1,2,3,4]],则zip 部分需要更改为:

arrs[0].zip(arrs[1], arrs[2], arrs[3])

对于两个输入数组,我可以这样写:

def mapcar2(fn, *arrs)
  return [] if arrs.empty? or arrs.include? []
  arrs[0].zip(arrs[1]).map do |e|
    e.reduce(&fn) unless e.include? nil
  end.compact
end

但我不知道如何超越两个以上的数组:

def mapcar(fn, *arrs)
  # Do not know how to abstract this
  # zipped = arrs[0].zip(arrs[1], arrs[2]..., arrs[n-1])
  # where n is the size of arrs
  zipped.map do |e| 
    e.reduce(&fn) unless e.include?(nil)
  end.compact
end

有人有什么建议吗?

【问题讨论】:

    标签: ruby


    【解决方案1】:

    如果我正确地回答了你的问题,你只需要:

    arrs = [[1,2], [3,4], [5,6]]
    zipped = arrs[0].zip(*arrs[1..-1])
    # => [[1, 3, 5], [2, 4, 6]] 
    

    或者更好的选择,IHMO:

    zipped = arrs.first.zip(*arrs.drop(1))
    

    如果arrs 中的所有数组长度相同,您可以使用transpose 方法:

    arrs = [[1,2], [3,4], [5,6]]
    arrs.transpose
    # => [[1, 3, 5], [2, 4, 6]] 
    

    【讨论】:

    • 啊。我试过这个:arrs[0].zip(arrs[1..-1]) 但没有用,谢谢!我想知道这个明星到底在做什么?
    • @juanitofatas 星号是 splat 运算符。您可以在 SO 上找到很多关于它的问题,例如:stackoverflow.com/questions/4170037/…
    • 我发现我以前也问过同样的问题:stackoverflow.com/questions/17341053/… 再次感谢。我会再学习的!
    • 嗯。你有找到数组元素长度相同的好方法吗?这看起来很糟糕:arrs.map { |e| e.size }.uniq.size == 1
    • @juanitofatas 问一个问题! :-)
    【解决方案2】:

    根据 toro2k,Ruby 中 mapcar 的可能实现之一:

    def mapcar(fn, *arrs)
      return [] if arrs.empty? or arrs.include? []
      transposed = if arrs.all? { |a| arrs.first.size == a.size }
                     arrs.transpose
                   else
                     arrs[0].zip(*arrs.drop(1))
                   end
      transposed.map do |e|
        e.collect(&fn) unless e.include? nil
      end.compact!
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-08
      • 2020-08-16
      • 2020-12-18
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多