F # Seq diff

заданы две последовательности, как получить все элементы, принадлежащие как последовательностям, так и всем элементам, уникальным для одного из них?

Пример:

let a = [1..10]
let b = [3; 5; 7]

Как я могу вычислить 3 5 и 7 (все элементы, общие для обоих списков) и 1, 2, 4, 6, 8, 9, 10 (все элементы не являются общими)

Спасибо

Ответы

Ответ 1

То, что вы хотите сделать, - это не более чем простые операции с установками intersection и difference (или относительное дополнение).

F # имеет модуль Set, чтобы помочь нам здесь. Это должно выполнить эту задачу:

let a = [1 .. 10]
let b = [3; 5; 7]

let intersection = Set.intersect (Set.ofList a) (Set.ofList b)
let difference = (Set.ofList a) - (Set.ofList b)

Затем вы можете, конечно, преобразовать результаты в списки, используя Set.toList, если хотите.

Как указывает Мехрдад, это может быть сделано альтернативно, используя LINQ (или даже класс HashSet в BCL), но подход здесь будет, по-видимому, наиболее в духе языка F # (безусловно, красиво синтаксически, и, вероятно, самый эффективный тоже).

Ответ 2

Чуть более компактный:

let a = set [0;1;2;3]
let b = set [2;3;4;5]
let c = a - b
let d = b - a
let e = Set.intersect a b
let f = a + b
> 
val c : Set<int> = seq [0; 1]
val d : Set<int> = seq [4; 5]
val e : Set<int> = seq [2; 3]
val f : Set<int> = seq [0; 1; 2; 3; ...]

Дэнни

Ответ 3

Не очень F # -у, каким я знаю. Вы всегда можете прибегать к библиотекам .NET. seq<T> просто IEnumerable<T>, ничего особенного:

let diff = System.Linq.Enumerable.Except(seq1, seq2); // seq1 - seq2
let intersect = System.Linq.Enumerable.Intersect(seq1, seq2);
let symdiff = System.Linq.Enumerable.Union(System.Linq.Enumerable.Except(seq1, seq2), System.Linq.Enumerable.Except(seq2, seq1));