Morshed Alam
Morshed Alam

Reputation: 153

Combine a two dimensional array of items

I have an set of array like this [ [1,2], [2, 3], [4,5], [5, 6,], [7, 8], [1,8,9]].if one item intersect with another then union those items.But I get duplicate items like [[1,2], [2,3], [1,8,9],[1,2,3,8,9][4,5],[5,6], [4,5,6],[7,8]], Where those set of items [1,2],[2,3][1,8,9],[4,5],[5,6],[7,8] are duplicate.

I tried to use reduce method but the output I expected still didn't get it.

   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
        }}

Here is my expected output [[1,2,3,7,8,9], [4, 5, 6] ] want to achieve.

Upvotes: 3

Views: 281

Answers (3)

Gleb A.
Gleb A.

Reputation: 1180

Just for fun, tried to stick with 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}]

But the part I'm really curious about is, how is it related to UICollectionViewLayoutAttributes? :-)

Upvotes: 2

RajeshKumar R
RajeshKumar R

Reputation: 15748

Create an empty array result with type [[Int]]. If intersection of current Set with any element of result is not empty, update the Set with its union. Else append the Set in result array.

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)
}

Call this method with the array

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]]

Upvotes: 2

Fabio Felici
Fabio Felici

Reputation: 2906

Try this code:

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() }
}

Upvotes: 2

Related Questions