Samthebest'in özlü çözümü, sadeliği ve zarafetiyle çok tatmin edici, ancak çok sayıda setle çalışıyorum ve hala işlevsel ve iyi işlevsel tarzda yazılmış daha performanslı bir çözüme ihtiyacım var.
Her biri 10 elementli 10,000 set için (rastgele seçilen 0 - 750.000 arası), samthebest'in ters çözümü bilgisayarımda ortalama ~ 30 saniye sürdü, benim çözümüm ise ortalama olarak 400 ms aldı.
kimse herhangi bir yenilik görebiliyorsanız
I tarzı bakımından yapabilir (herkes merak durumda, yukarıdaki set kardinallikleri için çıkan kümesi ~ 26 elementlerin ortalama her biriyle, ~ 3600 setleri içerir) veya performans, lütfen bana bildirin! (Filtresinde Pars içinde _ sahip olamaz) derlemek etmez
val sets = Set(Set(1, 2), Set(2, 3), Set(4, 5))
Association.associate(sets) => Set(Set(1, 2, 3), Set(4, 5))
object Association {
// Keep track of all current associations, as well as every element in any current association
case class AssociationAcc[A](associations: Set[Set[A]] = Set.empty[Set[A]], all: Set[A] = Set.empty[A]) {
def +(s: Set[A]) = AssociationAcc(associations + s, all | s)
}
// Add the newSet to the set associated with key A
// (or simply insert if there is no such key).
def updateMap[A](map: Map[A, Set[A]], key: A, newSet: Set[A]) = {
map + (key -> (map.getOrElse(key, Set.empty) ++ newSet))
}
// Turn a Set[Set[A]] into a map where each A points to a set of every other A
// it shared any set with.
//
// e.g. sets = Set(Set(1, 2), Set(2, 3), Set(4, 5))
// yields: Map(1 -> Set(2), 2 -> Set(1, 3), 3 -> Set(2),
// 4 -> Set(5), 5 -> Set(4))
def createAssociationMap[A](sets: Set[Set[A]]): Map[A, Set[A]] = {
sets.foldLeft(Map.empty[A, Set[A]]) { case (associations, as) =>
as.foldLeft(associations) { case (assoc, a) => updateMap(assoc, a, as - a) }
}
}
// Given a map where each A points to a set of every A it is associated with,
// and also given a key A starting point, return the total set of associated As.
//
// e.g. with map = Map(1 -> Set(2), 2 -> Set(1, 3), 3 -> Set(2),
// 4 -> Set(5), 5 -> Set(4))
// and key = 1 (or 2 or 3) yields: Set(1, 2, 3).
// with key = 4 (or 5) yields: Set(4, 5)
def getAssociations[A](map: Map[A, Set[A]], key: A, hit: Set[A] = Set.empty[A]): Set[A] = {
val newAssociations = map(key) &~ hit
newAssociations.foldLeft(newAssociations | hit + key) {
case (all, a) => getAssociations(map, a, all)
}
}
// Given a set of sets that may contain common elements, associate all sets that
// contain common elements (i.e. take union) and return the set of associated sets.
//
// e.g. Set(Set(1, 2), Set(2, 3), Set(4, 5)) yields: Set(Set(1, 2, 3), Set(4, 5))
def associate[A](sets: Set[Set[A]]): Set[Set[A]] = {
val associationMap = createAssociationMap(sets)
associationMap.keySet.foldLeft(AssociationAcc[A]()) {
case (acc, key) =>
if (acc.all.contains(key)) acc
else acc + getAssociations(associationMap, key)
}.associations
}
}
:
Burada ile geldi budur. Bunu düzeltmek için düzenledim ve denediğim bir test vakasında çalışıyorum :) –
@Paul Thx, ve aslında düzeltdiğim bir hata vardı. Ayrıca düşünürüm - kullanımdan kaldırıldı, bu yüzden filtre olarak değiştirilmediNot – samthebest
'bölümü 'kesimleri ve diğerleriyle kümelere bölmek için' bölümü' kullanabilir misiniz? Biraz daha açık olabilir mi? –