マルチセット(バッグ)とその操作について説明しているようです。
適切なデータ構造を使用すると、操作は非常に簡単に実装できます。
// Assume that X, Y are initialized bags
let matches = X.IntersectWith(Y)
let x = X.Difference(Y)
let y = Y.Difference(X)
.NET フレームワークには組み込みの Bag コレクションはありません。上記の関数署名が取られるBag クラスを含む Power Collection ライブラリを使用できます。
アップデート:
弱昇順のリストでバッグを表すことができます。F# 構文での @kqr の回答の改良版を次に示します。
let overlap xs ys =
let rec loop (matches, ins, outs) xs ys =
match xs, ys with
// found a match
| x::xs', y::ys' when x = y -> loop (x::matches, ins, outs) xs' ys'
// `x` is smaller than every element in `ys`, put `x` into `ins`
| x::xs', y::ys' when x < y -> loop (matches, x::ins, outs) xs' ys
// `y` is smaller than every element in `xs`, put `y` into `outs`
| x::xs', y::ys' -> loop (matches, ins, y::outs) xs ys'
// copy remaining elements in `xs` to `ins`
| x::xs', [] -> loop (matches, x::ins, outs) xs' ys
// copy remaining elements in `ys` to `outs`
| [], y::ys' -> loop (matches, ins, y::outs) xs ys'
| [], [] -> (List.rev matches, List.rev ins, List.rev outs)
loop ([], [], []) (List.sort xs) (List.sort ys)
List.sort
おそらく である を2 回呼び出した後O(nlogn)
、一致を見つけることは、2 つのリストの長さの合計に比例します。
手っ取り早いバッグ モジュールが必要な場合は、次のようなモジュール シグネチャをお勧めします。
type Bag<'T> = Bag of 'T list
module Bag =
val count : 'T -> Bag<'T> -> int
val insert : 'T -> Bag<'T> -> Bag<'T>
val intersect : Bag<'T> -> Bag<'T> -> Bag<'T>
val union : Bag<'T> -> Bag<'T> -> Bag<'T>
val difference : Bag<'T> -> Bag<'T> -> Bag<'T>