title: Swift: Transforming an Array of [A, B, B, B, A, B, B, B] into an Array of Hash [ [A: [B, B, B], [A: [B, B, B]] ]
body: <p>I have 2 kinds of struct, <code>Header</code> and <code>Session</code>, both conforming to protocol <code>TimelineItem</code>.<br>
  I have an <code>Array</code> composed of <code>TimelineItem</code>like this:<br>
  <code>[Header1, SessionA, SessionB, Header2, SessionC, SessionD]</code>   </p>
  
  <p>My need is to group <code>Session</code> under related <code>Header</code> like this:<br>
  <code>[ [Header1: [SessionA, SessionB], [Header2: [SessionC, SessionD] ]</code></p>
  
  <p>I tried using <code>filter</code> method to retrieve only <code>Header</code> struct, and <code>split</code> method to retrieve an Array of <code>Session</code> Array. These work fine but I cannot manage how to reconcile both to build my final <code>[[Header: [Session]]]</code> object.</p>
  
  <p>Here is my sample code:</p>
  
  <pre><code>enum TimelineItemType: String {  
    case Header = "header"   
    case Session = "session"
  }
  
  protocol TimelineItem {
    var id: Int { get }
    var type: TimelineItemType { get }
    var startDate: NSDate { get }
  }
  </code></pre>
  
  <p>The <code>Header</code> struct </p>
  
  <pre><code>struct Header: TimelineItem, Decodable, Hashable, Equatable {
    let id: Int
    let type: TimelineItemType = .Header
    let startDate: NSDate
    let text: String
  
    init?(json: JSON) {
      guard let id: Int = "id" &lt;~~ json,
        let type: TimelineItemType = "type" &lt;~~ json,
        let startDate: NSDate = "startDate" &lt;~~ json,
        let text: String = "text" &lt;~~ json where type == .Header else {
          return nil
      }
      self.id = id
      self.startDate = startDate
      self.text = text
    }
  
    var hashValue: Int {
      // As id is unique, we can use it for hash purpose
      return id
    }
  }
  </code></pre>
  
  <p>The <code>Session</code> struct</p>
  
  <pre><code>struct Session: TimelineItem, Decodable, Equatable {
    let id: Int
    let type: TimelineItemType = .Session
    let startDate: NSDate
    let name: String
    let syllabus: String
    let speaker: Speaker
    let language: String
    let room: String
    let duration: Int
  
    init?(json: JSON) {
      guard let id: Int = "id" &lt;~~ json,
        let type: TimelineItemType = "type" &lt;~~ json,
        let startDate: NSDate = Decoder.decodeDateISO8601("startDate")(json),
        let name: String = "name" &lt;~~ json,
        let speaker: Speaker = "speaker" &lt;~~ json,
        let syllabus: String = "syllabus" &lt;~~ json,
        let language: String = "language" &lt;~~ json,
        let room: String = "room" &lt;~~ json,
        let duration: Int = "duration" &lt;~~ json where type == .Session else {
          return nil
      }
      self.id = id
      self.startDate = startDate
      self.name = name
      self.speaker = speaker
      self.syllabus = syllabus
      self.language = language
      self.room = room
      self.duration = duration
    }
  }
  </code></pre>
  
  <p>And finally the code I tried to split my Array:</p>
  
  <pre><code>func timelineFromItems(timelineItems: [TimelineItem]) -&gt; [[Header: [Session]]]? {
  
      let slicedSessions = timelineItems.split { $0 is Header }
      let sessions = Array(slicedSessions)
      let headers = timelineItems.filter { $0.type == .Header }
      var timeline = [[Header: [Session]]]()
      // HOW TO FILL THE TIMELINE ??
  }
  </code></pre>
  
  <p><strong>HOW TO FILL THE TIMELINE ?</strong></p>