5

APL では、ビット ベクトルを使用して別のベクトルの要素を選択できます。これは圧縮と呼ばれます。たとえば、1 0 1/3 5 7 は 3 7 になります。

関数型プログラミング全般、特に F# でこれを表す用語はありますか?

これが私のF#プログラムです:

let list1 = [|"Bob"; "Mary"; "Sue"|]
let list2 = [|1; 0; 1|]

[<EntryPoint>]
let main argv = 

    0 // return an integer exit code

私がやりたいのは、[|"Bob"; となる新しい string[] を計算することです。スー"|]

F# でこれを行うにはどうすればよいでしょうか。

4

4 に答える 4

6
Array.zip list1 list2                 // [|("Bob",1); ("Mary",0); ("Sue",1)|]
|> Array.filter (fun (_,x) -> x = 1)  // [|("Bob", 1); ("Sue", 1)|]
|> Array.map fst                      // [|"Bob"; "Sue"|]

パイプ演算子|>は、構文的に逆の関数適用を行います。つまり、x |> fと同等f xです。別の回答で述べたように、中間配列の構築を避けるために置き換えArrayますSeq

F# に欠けている多くの APL プリミティブが見つかると思います。Seqリストとシーケンスの場合、上記のように、 、Array、またはListモジュールのプリミティブをつなぎ合わせることで、多くのリストを構築できます。参考までに、モジュールの概要を以下に示します。Seq

于 2014-03-30T09:38:06.730 に答える
1

これはより慣用的であると言う人もいるかもしれません:

Seq.map2 (fun l1 l2 -> if l2 = 1 then Some(l1) else None) list1 list2
|> Seq.choose id
|> Seq.toArray

EDIT(パイプ愛好家向け)

(list1, list2)
||> Seq.map2 (fun l1 l2 -> if l2 = 1 then Some(l1) else None)
|> Seq.choose id
|> Seq.toArray
于 2014-03-30T11:07:05.530 に答える
0

Søren Debois のソリューションは優れていますが、彼が指摘したように、もっとうまくやることができます。Søren のコードに基づいて、関数を定義しましょう。

let compressArray vals idx =
    Array.zip vals idx
        |> Array.filter (fun (_, x) -> x = 1)
        |> Array.map fst

compressArray3行のそれぞれに新しい配列を作成することになります。入力配列が長い場合、これには時間がかかることがあります (私の簡単なテストでは 10M の値で 1.4 秒)。
シーケンスに取り組み、最後にのみ配列を作成することで、時間を節約できます。

let compressSeq vals idx =
    Seq.zip vals idx
        |> Seq.filter (fun (_, x) -> x = 1)
        |> Seq.map fst

この関数は一般的で、配列、リストなどで機能します。出力として配列を生成するには:

compressSeq sq idx |> Seq.toArray

後者は計算時間の約 40% を節約します (私のテストでは 0.8 秒)。

ildjarn がコメントしたように、関数の引数をfilterに書き換えることができますがsnd >> (=) 1、おそらく生成される余分な関数呼び出しが原因で、パフォーマンスがわずかに低下します (< 10%)。

于 2014-03-31T08:41:16.077 に答える