我想在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
有人有任何建议吗?
答案 0 :(得分: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]]
答案 1 :(得分:0)
根据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