Skip to content

Instantly share code, notes, and snippets.

@aryaxt
Last active February 4, 2020 13:55
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aryaxt/ed9de5b14956df6f0efa to your computer and use it in GitHub Desktop.
Save aryaxt/ed9de5b14956df6f0efa to your computer and use it in GitHub Desktop.
Swift Array GroupBy
extension Sequence {
func groupBy<G: Hashable>(closure: (Iterator.Element)->G) -> [G: [Iterator.Element]] {
var results = [G: Array<Iterator.Element>]()
forEach {
let key = closure($0)
if var array = results[key] {
array.append($0)
results[key] = array
}
else {
results[key] = [$0]
}
}
return results
}
}
// Usage
var users: [User]
users.gourpBy { $0.age }
@moesalih
Copy link

This doesn't seem to work in Swift 1.2

@MonsieurDart
Copy link

MonsieurDart commented Apr 26, 2016

extension Array {

    func groupBy<G: Hashable>(groupClosure: (Element) -> G) -> [G: [Element]] {
        var dictionary = [G: [Element]]()

        for element in self {
            let key = groupClosure(element)
            var array: [Element]? = dictionary[key]

            if (array == nil) {
                array = [Element]()
            }

            array!.append(element)
            dictionary[key] = array!
        }

        return dictionary
    }
}

// Usage.
struct User { var age = 0 }

let users: [User] = [User(age: 2), User(age: 4), User(age: 5)]

let groupedUser = users.groupBy { $0.age }
groupedUser

@alekseypotapov-dev
Copy link

Extended version of @MonsieurDart for array of arrays in Swift 2.2

extension Array {

    func groupBy<G: Hashable>(groupClosure: (Element) -> G) -> [[Element]] {
        var groups = [[Element]]()

        for element in self {
            let key = groupClosure(element)
            var active = Int()
            var isNewGroup = true
            var array = [Element]()

            for (index, group) in groups.enumerate() {
                let firstKey = groupClosure(group[0])
                if firstKey == key {
                    array = group
                    active = index
                    isNewGroup = false
                    break
                }
            }

            array.append(element)

            if isNewGroup {
                groups.append(array)
            } else {
                groups.removeAtIndex(active)
                groups.insert(array, atIndex: active)
            }
        }

        return groups
    }
}

//Usage 
struct User { var age = 0 }
let users: [User] = [User(age: 2), User(age: 4), User(age: 5), User(age: 5), User(age: 2)]
let groupedUser = users.groupBy { $0.age }
print(groupedUser)

@Quaggie
Copy link

Quaggie commented Dec 14, 2016

Update for Swift 3

extension Array {
    func groupBy<G: Hashable>(groupClosure: (Element) -> G) -> [[Element]] {
        var groups = [[Element]]()
        
        for element in self {
            let key = groupClosure(element)
            var active = Int()
            var isNewGroup = true
            var array = [Element]()
            
            for (index, group) in groups.enumerated() {
                let firstKey = groupClosure(group[0])
                if firstKey == key {
                    array = group
                    active = index
                    isNewGroup = false
                    break
                }
            }
            
            array.append(element)
            
            if isNewGroup {
                groups.append(array)
            } else {
                groups.remove(at: active)
                groups.insert(array, at: active)
            }
        }
        
        return groups
    }
}

@NinoScript
Copy link

This one was closer to what I was looking for: http://stackoverflow.com/a/31220067/1904287

@aryaxt
Copy link
Author

aryaxt commented Jun 10, 2017

Updated code for swift 3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment