Last active
April 20, 2017 17:37
-
-
Save im-jersh/6be7e5bd62a0ec377dce8c5e8c35b6d7 to your computer and use it in GitHub Desktop.
Group elements of array by some property
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Foundation | |
| internal protocol Groupable { | |
| associatedtype GroupingType : Hashable | |
| var groupingKey : GroupingType? { get } | |
| } | |
| extension Array where Element : Groupable { | |
| typealias GroupingType = Element.GroupingType | |
| func grouped(nilsAsSingleGroup nilsAsSingleGroup: Bool = false) -> [[Element]] { | |
| var groups = [Int : [Element]]() | |
| var groupsOrder = [Int]() | |
| let nilGroupingKey = UUID().uuidString.hashValue | |
| var nilGroup = [Element]() | |
| for element in self { | |
| // If it has a grouping key then use it. Otherwise, conditionally make one based on if nils get put in the same bucket or not | |
| var groupingKey = element.groupingKey?.hashValue ?? UUID().uuidString.hashValue | |
| if nilsAsSingleGroup, element.groupingKey == nil { groupingKey = nilGroupingKey } | |
| // Group nils together | |
| if nilsAsSingleGroup, element.groupingKey == nil { | |
| nilGroup.append(element) | |
| continue | |
| } | |
| // Place the element in the right bucket | |
| if let _ = groups[groupingKey] { | |
| groups[groupingKey]!.append(element) | |
| } else { | |
| // New key, track it | |
| groups[groupingKey] = [element] | |
| groupsOrder.append(groupingKey) | |
| } | |
| } | |
| // Build our array of arrays from the dictionary of buckets | |
| var grouped = groupsOrder.flatMap{ groups[$0] } | |
| if nilsAsSingleGroup, !nilGroup.isEmpty { grouped.append(nilGroup) } | |
| return grouped | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment