2012-01-23 5 views
3

예 : list = [1,2,3,4]. listProduct list[1,2,3,4,6,8,9,12,16]을 반환합니다. 즉 [(1*1),(1*2),(1*3),(1*4),(2*3),(2*4),(3*3),(3*4),(4*4)]목록의 요소에 다른 모든 요소를 ​​곱하면 어떻게됩니까?

나는이 일을보고 기억하지만 더 이상 그 자원을 찾을 수 없습니다. 당신은 지능형리스트 사용하여 간단한 방법으로이 쓸 수

+2

결과에 '2 * 2'가 포함되지 않은 이유는 무엇입니까? 아마도 당신은 중복을 원하지 않을 것입니다. 그런데 왜 당신의 예제는 결과에'3 * 3'을 포함하지 않는 걸까요? – dave4420

+0

그건 오타되었습니다, 고마워요! 업데이트되었습니다. – ryanmehta

답변

5

결과에 2*2이 포함되지 않은 이유는 무엇입니까?

당신이 중복 싶어하는 경우 경우가 --- 다음 --- --- 즉, 당신이 중복 싶지 않은 반면에

listProduct xs = nub [x * y | x <- xs, y <- xs] 

1*4 같은 때문에이 있다면

: 당신은 최초의 솔루션의보다 효율적인 버전에서 triangularAutoZipWith을 사용할 수있는 다음 --- 결과에

listProduct' xs = triangularAutoZipWith (*) 

triangularAutoZipWith op = concatMap f . tails 
    where f [] = [] 
     f xs @ (x : _) = map (op x) xs 

을 중복 목록의 각 연속 번호로 각 숫자를 곱하고, 포함 할 당신이있는 경우 중복으로

listProduct = nub . triangularAutoZipWith (*) 
+0

Thanks. 나는 너를 사용하지 않으려 고했다. 그것은 중뇌가 심각한 성적 반향을 일으키는 것처럼 보입니다. 이것이 효과가 있지만. – ryanmehta

9

:

import Control.Monad 

listProduct = join $ liftM2 (*) 

(listProduct xs = liftM2 (*) xs xs에 해당)

그러나

listProduct xs = [x * y | x <- xs, y <- xs] 

, 그것은리스트 모나드를 사용하는 것이 더 관용적이다

이 버전을 이해하려면 (liftM2 (,)은 데카르트 제품 자체).

listProduct xs = concatMap (\x -> map (x *) xs) xs 

(당신이 기술적으로하지 않습니다 :

liftM2 f mx my = do { x <- mx; y <- my; return (f x y) } 
-- expand the do notation 
liftM2 f mx my = mx >>= (\x -> my >>= (\y -> return (f x y))) 
-- substitute the list monad's definition of (>>=) 
liftM2 f mx my = concatMap (\x -> concatMap (\y -> [f x y]) my) mx 
-- simplify 
liftM2 f mx my = concatMap (\x -> map (\y -> f x y) my) mx 
-- simplify again 
liftM2 f mx my = concatMap (\x -> map (f x) my) mx 

그래서 listProduct의 모나드 정의로 확장 : 그것은 당신이 목록 모나드에 liftM2의 정의를 전문으로하는 경우이 어떻게 작동하는지보기 위해 쉽게 여기에 전체 목록 모나드가 필요합니다. 목록의 경우 Applicative 인스턴스가 필요하고 listProduct = join $ liftA2 (*)도 작동하지만 모나드 정의와 함께 작동하는 방법을 표시하는 것이 더 쉽습니다. 목록의 Applicative 인스턴스는 다음과 같이 정의됩니다. Monad 인스턴스)

4

사용 ...

import Control.Applicative 

...

listProduct list = (*) <$> list <*> list 

... 그리고없이 ...

listProduct list = concat (mul <$> list <*> list) where 
    mul a b | a <= b = [a*b] 
      | otherwise = [] 

루브 - 골드버그 - 분위기, 당신은 사용할 수 ...

listProduct list = concat $ zipWith (map.(*)) list (map ((`filter` list).(<=)) list) 

... 또는 간단하게 ...

import Data.List 

listProduct list = concat $ zipWith (map.(*)) list $ tails list 

[편집]

또 다른 방법은 sequence을 사용하는 것입니다.

listProduct = map product . sequence . replicate 2 

없이 : 중복으로

listProduct = map product . filter(\[a,b] -> a <= b) . sequence . replicate 2 
1

글쎄, 당신은 이미 몇 가지 답변을 있어요,하지만 난 이전의 것들을 생각하기 때문에 모두 정확하면서 내에서 던져거야 도움이 될 수 없습니다.

당신이 이해하는 초보자 왔 가장 쉬운 솔루션은 지능형리스트입니다 :

example1 = [ x*y | x <- list, y <- list ] 

이 구문은 파이썬 같은 일부 인기있는 언어로 존재하며, 어떤 경우에 쉽게 이해할 수 있어야합니다 "는 요소가 x*y의 결과 인 목록의 경우 이 listy의 요소 인 경우 목록의 요소는 list입니다.

example2 = [ x*y | x <- list, y <- list, x /= y ] 

더 복잡한 대답은 지능형리스트가 동등하다는 사실과해야 할 : 당신은 또한 어디에 x == y 당신이 제품을 원하지 않는 경우, 예를 들어, 일부 조합을 필터링 지능형리스트에 조건을 추가 할 수 있습니다 목록 모나드; 목록 유형에 대한 표준 형식 인 Monad의 구현. 이 example1는 이러한 방식으로 구현 될 수 있다는 것을 의미한다 :

example1' = do x <- list 
       y <- list 
       return (x*y) 

do 표기법이 단지 문법 설탕입니다 :

Landei의 대답은 사실에 기초
example1'' = list >>= (\x -> list >>= (\y -> return (x*y))) 

당신이하지 않은 경우 귀하의 목록 이해력에있는 어떤 조건을 사용하여, 그냥 데카르트 제품, 당신은 떨어져 보다는 약한 Applicative 유형 클래스를 사용하여 얻을 수 있습니다.

관련 문제