たとえば、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)]
リストの要素に他のすべての要素を掛けるにはどうすればよいですか?
私はこれを行ったことがあることを覚えていますが、私はそのリソースをこれ以上見つけることができません。
たとえば、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
が含まれていないのはなぜですか?
あなたは重複をしたいです場合ならば、それは---、その後、--- ---つまり、あなたが重複を望んでいない一方
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 (*)
ありがとうございます。私はナブの使用を避けたいと思っていました。それは、ナブがいくつかの重大なパフォーマンスへの影響を与えているようです。これは動作しますが。 – ryanmehta
あなたはリストの内包表記を使用して簡単な方法でこれを書くことができます。
listProduct xs = [x * y | x <- xs, y <- xs]
しかし、それはリストモナドを使用することがより慣用的です:(listProduct xs = liftM2 (*) xs xs
に相当)
import Control.Monad
listProduct = join $ liftM2 (*)
を
このバージョンを理解するには、liftM2
を一般的な種類のCartesian productと考えることができます(liftM2 (,)
はデカルト積自体)。それはあなたがリストモナドにliftM2
の定義を専門とする場合は、この動作を確認する方が簡単です:
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
のモナドの定義は次のように拡張されます
listProduct xs = concatMap (\x -> map (x *) xs) xs
(あなたがいない技術的に行うことに注意してくださいここではリスト全体のモナドが必要です;リストの場合はApplicative
インスタンスが必要ですが、listProduct = join $ liftA2 (*)
も同様に動作しますが、リストのApplicative
インスタンスは次のように定義されています。 Monad
インスタンス。 )
使用して...
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
さて、あなたはすでにいくつかの答えを持っているが、私は以前のものをと思うので、すべて正確一方で、鉱山でトスするつもりです不十分に役立つかもしれません。
あなたが理解する初心者のために得ている最も簡単な解決策は、リスト内包である:
example1 = [ x*y | x <- list, y <- list ]
この構文は、Pythonのようないくつかの一般的な言語に存在し、どのような場合には、理解しやすいようになります。「要素がx*y
の結果であるリストを返します。ここで、x
は、list
とy
の要素です。list
の要素です。あなたがx == y
の製品を使用しない場合にも、例えば、いくつかの組み合わせをフィルタリングするために、リストの内包表記に条件を追加することができます。
example2 = [ x*y | x <- list, y <- list, x /= y ]
より複雑な答えがリストの内包表記と等価であるという事実に関係していますリストMonad;リストタイプの標準タイプMonad
の実装。
example1' = do x <- list
y <- list
return (x*y)
do
-notationは、このためだけの構文糖である:
example1'' = list >>= (\x -> list >>= (\y -> return (x*y)))
Landeiの答えはあなたがいないのであればという事実に基づいているこれはexample1
またこれらの方法で実装することができることを意味しあなたのリストの理解の任意の条件を使用して、デカルト製品だけでより弱いApplicative
タイプのクラスを使用して離れて得ることができます。
あなたの例題に結果に '2 * 2'が含まれていないのはなぜですか?おそらく、あなたは重複を望まないでしょう。しかし、なぜあなたの例は結果に '3 * 3'を含まないのでしょうか? – dave4420
それはタイプミスでした、ありがとう!今更新されました – ryanmehta