Объедините двумерный массив предметов - PullRequest
3 голосов
/ 15 мая 2019

У меня есть набор таких массивов [[1,2], [2, 3], [4,5], [5, 6,], [7, 8], [1,8,9]]. если один элемент пересекается с другим, то объединить эти элементы. Но я получаю дубликаты, такие как [[1,2], [2,3], [1,8,9], [1,2,3,8,9] [4,5], [5,6], [4,5,6], [7,8]], где этот набор предметов [1,2], [2,3] [1,8,9], [4,5], [5,6], [7,8] дубликаты.

Я пытался использовать метод Reduce, но ожидаемый результат все равно не получил его.

   var newtotalOverlapingSet = Set<[UICollectionViewLayoutAttributes]>()

    if totoalOverLapArray.count > 0{
     let _ = totoalOverLapArray.reduce(totoalOverLapArray[0]){ firstSet, secondSet  in

            if firstSet.intersection(secondSet).count > 0{
                newtotalOverlapingSet.insert(Array(firstSet.union(secondSet)))
                return firstSet.union(secondSet)
            }
            return secondSet
        }}

Вот мой ожидаемый результат [[1,2,3,7,8,9], [4, 5, 6]], которого я хочу достичь.

Ответы [ 3 ]

2 голосов
/ 15 мая 2019

Попробуйте этот код:

func combine(input: [[Int]]) -> [[Int]] {
    return input
        .reduce([Set<Int>]()) { acc, elem in
            let set = Set(elem)
            return acc.firstIndex { !$0.isDisjoint(with: set) }
                .map { index in
                    acc.enumerated().compactMap {
                        if $0.offset == index {
                            return acc
                                .filter { !$0.isDisjoint(with: set) }
                                .reduce(Set()) { $0.union($1) }
                                .union(set)
                        }
                        return $0.element.isDisjoint(with: set) ? $0.element : nil
                    }
                } ?? acc + [set]
        }
        .map { Array($0).sorted() }
}
2 голосов
/ 15 мая 2019

Ради интереса, попробовал придерживаться reduce:

func mergeIntersections(of arrays: [[Int]]) -> [Set<Int>] {
    return arrays.reduce([Set<Int>]()) { result, nextChunk in
        let partialResult = result.reduce(into: (mergedChunk: Set(nextChunk), unmergedChunks: [Set<Int>]())) { (result, existingChunk) in
            if !result.mergedChunk.intersection(existingChunk).isEmpty {
                result.mergedChunk.formUnion(existingChunk)
            } else {
                result.unmergedChunks.append(existingChunk)
            }
        }

        return partialResult.mergedChunk.isEmpty
            ? partialResult.unmergedChunks
            : partialResult.unmergedChunks + [partialResult.mergedChunk]
    }
}

let arraysOfInts = [[1,2], [2,3], [4,5], [5,6], [7,8], [1,8,9]]
mergeIntersections(of: arraysOfInts) // [{6, 4, 5}, {2, 1, 7, 8, 9, 3}]

Но та часть, которая мне действительно интересна, как она связана с UICollectionViewLayoutAttributes? : -)

2 голосов
/ 15 мая 2019

Создать пустой массив result с типом [[Int]].Если intersection текущего Set с любым элементом result не является пустым, обновите Set его объединением.Иначе добавьте массив Set in result.

func group(arr: [[Int]]) -> [[Int]] {
    if (arr.reduce(0) { $0 + $1.count }) == Set(arr.reduce([Int](), +)).count {
        return arr
    }
    let result = arr.reduce(into: [[Int]]()) { (result, subArr) in
        if let index = result.firstIndex(where: { !Set($0).intersection(subArr).isEmpty }) {
            result[index] = Set(result[index]).union(subArr).sorted()
        } else {
            result.append(Array(subArr))
        }
    }
    return group(arr:result)
}

Вызовите этот метод с массивом

let arr1 = [[1,2], [2, 3], [4,5], [5, 6,], [7, 8], [1,8,9]]
print(group(arr: arr1))

[[1, 2, 3, 7, 8, 9], [4, 5, 6]]

let arr2 = [[1, 2], [2, 3], [4, 5], [5, 6], [7, 8], [1, 8, 9], [10, 9], [9, 6]]
print(group(arr: arr2))

[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...