2013-08-08 1 views
0

Ruby에 Lisp의 mapcar을 구현하고 싶습니다.루비에서 Common Lisp의 mapcar를 어떻게 구현합니까?

희망찬 구문 : 그럼 난 할 수

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

:하지만이 zip 부분에 붙어

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

=> [24, nil, nil] 

여기

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

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

은 내가 생각할 수있는 솔루션입니다 . 나는 이런 식으로 뭔가 쓸 수

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

두 입력 배열 : 입력이 [[1], [1,2], [1,2,3], [1,2,3,4]] 경우, zip 부분을 변경해야

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 

누구에게 조언이 있습니까? 내가 질문을 받았다면

답변

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]] 
+0

Ah. 나는 이것을 시도했다 : arrs [0] .zip (arrs [1 ..- 1])하지만 작동하지 않았다. 고마워! 나는이 별이 여기서 정확히 무엇을하고 있는지 궁금하다. – juanitofatas

+0

'drop (1)'은 굉장합니다! 대단히 감사합니다 !!!! – juanitofatas

+0

@juanitofatas 별은 표시 연산자입니다. 이렇게 많은 질문이 있습니다. 예 : http://stackoverflow.com/questions/4170037/what-does-the-star-mean-in-ruby/4170053. – toro2k

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 
관련 문제