Как оптимизировать следующий код


#1

Добрый вечер коллеги. Нужна ваша помощь.
Есть массив of Set и некоторые Set в нем могут содержать общие элементы. Такие Set нужно объединить в один Set и в итоге иметь массив Set которые не имели бы общих Int. Написал ниже код для этого. Но работает он все же медленно. Нужно уменьшить время, поскольку массив может быть до миллиона элементов.

    var combinableSet = Set<Int>()
    var oldCombinableSet = Set<Int>()
    
    for k in 0..<arrayOfCombinableReadsNumbers.count
    {
        if arrayOfCombinableReadsNumbers[k].isEmpty != true
        {
            combinableSet = arrayOfCombinableReadsNumbers[k]
            oldCombinableSet = Set<Int>()
            
            repeat
            {
                for i in 0..<arrayOfCombinableReadsNumbers.count
                {
                    oldCombinableSet = combinableSet
                    
                    if arrayOfCombinableReadsNumbers[i].isEmpty != true
                    {
                        if combinableSet != arrayOfCombinableReadsNumbers[i] && combinableSet.intersection(arrayOfCombinableReadsNumbers[i]).isEmpty != true
                        {
                            combinableSet = combinableSet.union(arrayOfCombinableReadsNumbers[i])
                            arrayOfCombinableReadsNumbers[k] = combinableSet
                            arrayOfCombinableReadsNumbers[i] = Set<Int>()
                            
                            break
                        }
                    }
                }
            }while oldCombinableSet != combinableSet
        }
    }
    var arrayOfSetsToCombine = arrayOfCombinableReadsNumbers.filter {$0.isEmpty != true}

#2

Ещё бы массив что бы протестировать, попробуйте так:

var array: [Set<Int>] = [
    [1, 0, 3],
    [1, 2, 5],
    [9, 10, 6],
    [0,  15]
]

for i in stride(from: array.endIndex - 1, through: array.startIndex, by: -1) where !array[i].isEmpty {
    for j in stride(from: array.endIndex - 1, through: i + 1, by: -1) where !array[j].isEmpty && !array[i].intersection(array[j]).isEmpty {
        array[i] = array[i].union(array[j])
        array.remove(at: j)
    }
}

print(array)

#3

Или лучше так:

var array: [Set<Int>] = [
    [1, 0, 3],
    [1, 2, 5],
    [9, 10, 6],
    [0,  15],
    [],
    [7, 74, 76]
]



for i in stride(from: array.endIndex - 1, through: array.startIndex + 1, by: -1) {
    for j in stride(from: i - 1, through: array.startIndex, by: -1) where !array[j].intersection(array[i]).isEmpty || array[i].isEmpty {
        array[j] = array[j].union(array[i])
        array.remove(at: i)
    }
}

#4

Спасибо!
Последний вариант выдает ошибку index out of range в условии второго цикла. Буду разбираться.


#5

а использовать множества под эту задачу не пробовали? Там вроде похожие функции

Используйте метод symmetricDifference(_:) для создания нового множества из значений, которые не повторяются в двух входных множествах.

Используйте метод subtracting (_:) для создания множества со значениями не принадлежащих указанному множеству из двух входных.

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