1

F# シーケンス式で自己参照を持つ方法はありますか? 例えば:

[for i in 1..n do if _f(i)_not_in_this_list_ do yield f(i)]

これにより、重複する要素の挿入が防止されます。

編集: 一般的に、計算コストが非常に高い f() を適用する前に、this_list の内容を知りたいと思います。

編集:上記の例では単純化しすぎています。私の特定のケースは、プロパティ T(i) => T(n*i) を持つ計算コストの高いテスト T (T: int -> bool) であるため、コード スニペットは次のようになります。

[for i in 1..n do if _i_not_in_this_list_ && T(i) then for j in i..i..n do yield j]    

目標は、T() アプリケーションの数を減らし、簡潔な表記を使用することです。変更可能なヘルパー配列を使用して前者を達成しました。

let mutable notYet = Array.create n true
[for i in 1..n do if notYet.[i] && T(i) then for j in i..i..n do yield j; notYet.[j] <- false]
4

3 に答える 3

2

ここにはいくつかの考慮事項があります。
まず、f(i)実際に計算する前に、リストにあるかどうかを確認することはできませんf(i)checkつまり、関数自体ではなく、関数が高価であることを意味していると思いますf(i)。私が間違っている場合は私を訂正してください。

第二に、実際に非常に計算コストがかかる場合checkは、より効果的なアルゴリズムを探すことができます。シーケンスごとに1つ見つかる保証はありませんが、多くの場合、存在します。そうすれば、あなたのコードはただ一つになります。Seq.unfold

第3。そのような最適化がない場合は、別のアプローチを取ることができます。内[for...yield]では、現在の要素のみを作成し、以前の要素にアクセスすることはできません。要素を返す代わりに、リスト全体を手動で作成するのが方法のようです。

// a simple algorithm checking if some F(x) exists in a sequence somehow
let check (x:string) xs = Seq.forall (fun el -> not (x.Contains el)) xs
// a converter i -> something else
let f (i: int) = i.ToString()

let generate f xs =
    let rec loop ys = function
        | [] -> List.rev ys
        | x::t ->
            let y = f x
            loop (if check y ys then y::ys else ys) t
    loop [] xs

// usage
[0..3..1000] |> generate f |> List.iter (printf "%O ")
于 2013-03-02T15:18:53.657 に答える
2

たとえば、再帰シーケンス式を使用できます

let rec allFiles dir =
    seq { yield! Directory.GetFiles dir
          for d in Directory.GetDirectories dir do
              yield! allFiles d }

ただし、循環参照はできません。

別の方法は、 SeqモジュールからSeq.distinctを使用することです。

seq { for i in 1..n -> f i }
|> Seq.distinct

または、@John のコメントに従って、消費前にSet.ofSeqを使用してシーケンスをセットに変換します。

于 2013-03-02T02:24:18.877 に答える
2

以前に生成された要素に関する情報を明示的に維持することもできます。例えば:

let genSeq n =
   let elems = System.Collections.Generic.HashSet()
   seq {
      for i in 1..n do
         if not (elems.Contains(i)) then
            elems.Add(i) |> ignore
            yield i
   }
于 2013-03-02T12:16:17.257 に答える