Ключ гарантирующего наборы исходных сортируются в порядке убывания размера , Таким образом, все надмножества предшествуют их подмножествам.
Вот общая функция для этого. Вы можете адаптировать его взять любую последовательность последовательности hashable и преобразовывать их в массив множеств на пути в:
func removeSubsets<T: Hashable>(source: [Set<T>]) -> [Set<T>] {
let sets = source.sorted { $0.count > $1.count }
var supersets: [Set<T>] = []
for set in sets {
if !contains(supersets, { set.isSubsetOf($0) }) {
supersets.append(set)
}
}
return supersets
}
removeSubsets([[2, 3, 4, 7, 8, 9, 10], [1, 5, 6], [3, 7, 10], [4, 8, 9], [5, 6], [7, 10], [8, 9], [6], [9]])
// returns [{10, 2, 9, 4, 7, 3, 8}, {5, 6, 1}]
Это еще кубическая, к сожалению, так как contains
линейна и так isSubsetOf
.
EDIT: вот полностью общая версия:
func removeSubsets
<S0: SequenceType, S1: SequenceType
where S0.Generator.Element == S1,
S1.Generator.Element: Hashable>
(source: S0) -> [Set<S1.Generator.Element>]
{
let sets = map(source) { Set($0) }.sorted { $0.count > $1.count }
var supersets: [Set<S1.Generator.Element>] = []
for set in sets {
if !contains(supersets, { set.isSubsetOf($0) }) {
supersets.append(set)
}
}
return supersets
}
let a: [[Int]] = [
[2, 3, 4, 7, 8, 9, 10],
[1, 5, 6], [3, 7, 10],
[4, 8, 9], [5, 6],
[7, 10], [8, 9],
[6], [9]]
removeSubsets(a) // returns [{10, 2, 9, 4, 7, 3, 8}, {5, 6, 1}]
EDIT2: если вы хотите, чтобы результат будет массивом исходных массивов (так как преобразование их в наборы теряет свою упорядоченность), вы можете сделать следующее изменение, которое занимает больше места, но также немного более эффективным, поскольку он преобразует только суперсетами к агрегатам, а не подмножества:
func removeSubsets<T: Hashable>(source: [[T]]) -> [[T]] {
// note, this is quite efficient since arrays are copy-on-write,
// so it is only really creating a new array of pointers
let sets = source.sorted { $0.count > $1.count }
var supersets: [Set<T>] = []
var result: [[T]] = []
for set in sets {
if !contains(supersets, { $0.isSupersetOf(set) }) {
supersets.append(Set(set))
result.append(set)
}
}
return result
}
removeSubsets([[2, 3, 4, 7, 8, 9, 10], [1, 5, 6], [3, 7, 10], [4, 8, 9], [5, 6], [7, 10], [8, 9], [6], [9]])
// returns [[2, 3, 4, 7, 8, 9, 10], [1, 5, 6]]
EDIT3: если вы хотите сохранить первоначальный порядок множеств (только с подмножествами удалены), вы можете пометить их числом по пути перед сортировкой, а затем повторно сортировать их, используя его, и отделить его от результата в конце:
func removeSubsets<T: Hashable>(source: [[T]]) -> [[T]] {
let sets = sorted(enumerate(source)) { $0.1.count > $1.1.count }
var supersets: [Set<T>] = []
var result: [(Int,[T])] = []
for (n,set) in sets {
if !contains(supersets, { $0.isSupersetOf(set) }) {
supersets.append(Set(set))
result.append(n,set)
}
}
return result.sorted { $0.0 < $1.0 }.map { $1 }
}
// note, input not sorted in order of length
removeSubsets([[1, 5, 6], [2, 3, 4, 7, 8, 9, 10], [3, 7, 10], [4, 8, 9], [5, 6], [7, 10], [8, 9], [6], [9]])
// returns [[1, 5, 6], [2, 3, 4, 7, 8, 9, 10]]
Являются ли эти массивы наборов или массивов массивов? И что именно вы хотите удалить? –
Массивы массивов, но я хотел бы удалить все подмножества. Например. [3, 7, 10] является подмножеством [2, 3, 4, 7, 8, 9 10] и т. Д., Оставляя только два надмножества. Мне нужен способ, кроме запуска isSubsetOf для каждого элемента, начиная с самого маленького набора. – jarryd
Если у вас есть директор о том, как вам нужно их удалить, возможно ... согласно предоставленной информации, вы можете получить выходной массив, если вы удалите каждый элемент из оригинала, индекс которого больше, чем '1'. – holex