2017-09-12 21 views
0

我寫查理士或字符的交叉產物?

iex(87)> cross=fn               
...(87)> a, b when is_list(a) and is_list(b) -> for x <- a, y <- b, do: [x,y] 
...(87)> a, b when not is_list(a) and is_list(b) -> for y<-b, do: [a,y]  
...(87)> a, b when is_list(a) and not is_list(b) -> for x<- a , do: [x, b] 
...(87)> end 

該做的事情,但天哪,這是非常難看。我試過簡單得多

cross=fn(a,b) -> for x <- to_charlist(a), y <- to_charlist(b), do: [x,y] end 

但是,當發送單個字符時,這樣做會產生很多假結果。

回答

0

所以你基本上想要的是一種將非列表包裝到單個元素列表中的方法,然後您的for將按照預期的方式使用char或charlists作爲參數。你可以用List.wrap/1做到這一點:

cross2 = fn as, bs -> 
    for a <- List.wrap(as), b <- List.wrap(bs), do: [a, b] 
end 

測試:

cross = fn               
    a, b when is_list(a) and is_list(b) -> for x <- a, y <- b, do: [x, y] 
    a, b when not is_list(a) and is_list(b) -> for y <- b, do: [a, y]  
    a, b when is_list(a) and not is_list(b) -> for x <- a , do: [x, b] 
end 

cross2 = fn as, bs -> 
    for a <- List.wrap(as), b <- List.wrap(bs), do: [a, b] 
end 

IO.inspect cross.('abc', 'def') 
IO.inspect cross2.('abc', 'def') 
IO.inspect cross.(?a, 'def') 
IO.inspect cross2.(?a, 'def') 
IO.inspect cross.('abc', ?d) 
IO.inspect cross2.('abc', ?d) 
# Your implementation doesn't handle this case. 
# IO.inspect cross.(?a, ?d) 
IO.inspect cross2.(?a, ?d) 

輸出:

['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf'] 
['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf'] 
['ad', 'ae', 'af'] 
['ad', 'ae', 'af'] 
['ad', 'bd', 'cd'] 
['ad', 'bd', 'cd'] 
['ad'] 
0

另一種方法是使用Kernel.to_string/1,有效地變平加入列表,並<<c <- string>>發電機:

cross3 = fn a, b ->        
    [a, b] = Enum.map([a, b], &Kernel.to_string([&1])) 
    for <<x::utf8 <- a>>, <<y::utf8 <- b>>, do: [x, y]    
end 

IO.inspect cross3.('abc', 'def') 
#⇒ ['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf'] 
IO.inspect cross3.(?a, 'def') 
#⇒ ['ad', 'ae', 'af'] 
IO.inspect cross3.('abc', ?d) 
#⇒ ['ad', 'bd', 'cd'] 
IO.inspect cross3.(?a, ?d) 
#⇒ ['ad'] 
+0

有一件事:你需要執行'x :: utf8'和'y :: utf8'來獲得與非ASCII輸入的charlists相同的行爲。 – Dogbert

+0

@Dogbert確實,謝謝,更新。 – mudasobwa