5

私はzipWith2つのシーケンスの対​​応する要素を操作する標準関数に精通していますが、関数型言語(またはいくつかの関数型機能を備えた言語)では、に基づいて、圧縮する要素のペアを条件付きで選択する最も簡潔な方法は何ですか? 3番目のシーケンス?

この好奇心は、Excelでいくつかのことをスクラッチしているときに発生しました。
A1:A10、B1:B10、C1:C10、D1、E1、F1の数字で、次のような式を使用しています。

{=AVERAGE(IF((D1<=(A1:A10))*((A1:A10)<=E1),B1:B10/C1:C10))}

IFステートメントの乗算の各半分は、ブール値の配列を生成し、それらは一緒に乗算(AND)されます。これらのブール値は、10個の商のどれが最終的に平均化されるかを制御するため、10個の個別のIFステートメントが評価されているかのようになります。

たとえば、A1:A10の10個の値の2番目と3番目だけが条件(> =D1と<=E1の両方)を満たす場合、式は次のように評価されます。

AVERAGE(FALSE,B2/C2,B3/C3,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE)

AVERAGE関数はたまたまブール値とテキスト値を無視するため、2番目と3番目の商の平均を取得するだけです。

これはHaskellで簡潔に行うことができますか?Erlang?LINQまたはF#?Python?等..

この特定の例では、上記の式が完全に正しいわけではないことに注意してください。基本的なポイントを理解するために省略されています。A1:A10の10個の要素のいずれも条件を満たさない場合、10個のFALSE値がAVERAGEに渡され、誤って0と評価され
ます。式は次のように記述する必要があります。

{=AVERAGE(IF(NOT(OR((D1<=(A1:A10))*((A1:A10)<=E1))),NA(),
             IF((D1<=(A1:A10))*((A1:A10)<=E1),B1:B10/C1:C10)))}

NA()がエラーを生成し、平均が未定義であることを示します 。

アップデート:

答えてくれてありがとう。最初のリストの対応する要素が特定の基準を満たしている場合に、2番目と3番目のリストの要素のペアに関数を適用するという点で、最初の質問は非常に簡単であることに気付きました。そのためのノーマン・ラムゼーの答えを受け入れました。

しかし、次に行ったのは、任意の数のリストからの対応する要素を表すタプルに関数を適用できるかどうか疑問でした。したがって、の制限についてLebertramに質問しましたzipWithN

適用可能なファンクターに関するApocalispの情報から、Pythonによる引数リストの解凍(任意の数の引数に関数を適用する)に関する情報が得られました。

上記の特定の例では、リストの要素の商を平均すると(numsリストのリストはここにあります)、Pythonは次のように実行できるように見えます。

from operator import div

def avg(a): return sum(a,0.0)/len(a)
avg([reduce(div,t[1:]) for t in zip(*nums) if d<=t[0] and t[0]<=e])

より一般的には、関数fと述語p(およびavg)を使用すると、これは次のようになります。

avg([f(t[1:]) for t in zip(*nums) if p(t[0])])
4

3 に答える 3

3

zip内の要素を条件付きで選択する方法は?

最初に圧縮し、後で選択します。

この場合、 で選択を行っていcatMaybesます。これは、この設定で役立つことがよくあります。型チェックを取得するのは非常に面倒でした (正確fromIntegralに正しい場所に配置する必要があります) が、いつものようにオプティマイザに依存して書くコードは次のとおりです。

average as bs cs d1 e1 = avg $ catMaybes $ zipWith3 cdiv as bs cs
  where cdiv a b c = if a >= d1 && a <= e1 then Just (b/c) else Nothing
        avg l = sum l / fromIntegral (length l)

関数cdivは「条件分割」の略です。

取得catMaybesするには、インポートする必要がありますData.Maybe

このコードは型チェックしますが、実行していません。

于 2010-02-21T23:41:08.870 に答える
1

ハスケル:

average . map fromJust . filter isJust $ zipWith3 (\a b c -> if a >= d1 && a <= e1 then Just b/c else Nothing) as bs cs
  where average xs = let (sum,n) = foldl' (\(s,m) x -> (s+x,m+1)) (0,0) xs in sum / (fromIntegral n)
于 2010-02-21T17:14:16.360 に答える