Samthebest의 간결한 솔루션은 단순함과 우아함이 매우 만족 스럽지만 많은 수의 세트로 작업하고 있으며 여전히 기능이 부족한 스타일로 작성된 더 우수한 솔루션이 필요합니다.
각각 10 개 요소 (무작위로 선택된 0 ~ 750,000의 정수)가있는 10,000 세트의 경우 samthebest의 간결한 솔루션은 내 컴퓨터에서 평균 ~ 30 초가 걸렸지 만 아래 솔루션은 평균 ~ 400ms가 걸렸습니다.
사람이 어떤 개선을 볼 수 있다면
나는 스타일에 대한 만들 수 (사람이 궁금 경우, 위의 설정 카디널리티에 대한 결과 집합 ~ 26 개 요소의 평균 각각 ~ 3600 개 세트 포함) 또는 성능, 알려 주시기 바랍니다! (필터에 괄호에 _ 당신은 할 수 없습니다) 컴파일되지 않습니다
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
}
}
:
는 여기에 내가 무엇을 최대 온입니다. 나는 그것을 고치기 위해 편집했고 시도한 하나의 테스트 케이스에서 작동한다. :) –
@ Paul Thx, 그리고 실제로 버그가 수정되었다. 또한 나는 생각 - - deprecated, 그래서 그것을 filterNot으로 바꾸었다. – samthebest
'partition'을 사용하여'cum'을 교차 부분과 나머지 부분으로 나눌 수 있습니까? 조금 더 명확해질 수 있을까요? –