0

I'm modelling a time series log in Swift using just an Array and a custom class that looks like:

class StatusEvent {
    var status:ValveStatus // this is just an enum
    var begin:NSDate
}

As I get updates to my log, I maintain the invariant that there are no duplicates (inferred by matching times) and that they are sorted in order by the begin property. My three uses for this data are:

  1. Access the latest (last) element (this happens a lot)
  2. Enumerate them in order (for visualizing the time series)
  3. Adding new values to the list, which happens on periodic updates, but not that much

I can do some quick checks like "is this an add past end or before front" which take care of a lot of them, but when I detect the case where I've got to insert somewhere in the middle, I came up with the following:

var begin = oldestLogEvent.begin
for index in 1..<self.statusLog.count {
    let event = self.statusLog[index]
    let end = event.begin
    if newEvent.begin == end {
        return false;
    }
    if begin < newEvent.begin && newEvent.begin < end {
        self.statusLog.insert(newEvent, atIndex: index)
        return true;
    }
    begin = end;
}

I return a Bool indicating whether an insertion happened or not.

Having ported this from Objective-C, I'm curious if Swift gives me some tools/idioms that would solve this "search for insertion point and conditionally insert" algorithm?

I'm open to using some other than an Array and simple event class; I looked at using a tree, but while that makes the insert potentially faster, I think it would cost more memory as well as make enumeration and last element access (my primary use cases) slower.

Travis Griggs
  • 21,522
  • 19
  • 91
  • 167
  • 1
    Why don't you just append and then sort? Sure, that would not be very efficient if you had 10000 elements and you did it a lot, but doing it for a small array once in a while won't bring the universe crashing down about your ears. – matt May 15 '15 at 16:10
  • 1
    This might possibly me helpful: [How do I insert an element at the correct position into a sorted array in Swift?](http://stackoverflow.com/questions/26678362/how-do-i-insert-an-element-at-the-correct-position-into-a-sorted-array-in-swift) – Martin R May 15 '15 at 16:15
  • I have considered doing exactly that. Just add and sort. Though I have to first check for existing so I don't add duplicates. – Travis Griggs May 15 '15 at 17:31

1 Answers1

1

First of all, in Swift, if you have no good reason to make something a class, make it a struct.

Second, in answer to your actual question, what I would do is far less computer-sciency than you seem to be envisioning: I would just make StatusEvent a Comparable (i.e. it knows that one StatusEvent is bigger than another if its begin is bigger) and then just append a new Status Event and sort the array on <.

This could have a second benefit; you will have to make StatusEvent an Equatable, and if you decide that two StatusEvents are equal if their begin are the same, you can just use find to determine whether a StatusEvent with the same begin is already present in the array.

Here's a simplified example (I'm using Int instead of Date):

func == (lhs:StatusEvent, rhs:StatusEvent) -> Bool {
    return lhs.begin == rhs.begin
}
func < (lhs:StatusEvent, rhs:StatusEvent) -> Bool {
    return lhs.begin < rhs.begin
}
struct StatusEvent : Comparable {
    var begin : Int = 0
}
var arr = [StatusEvent(begin:3), StatusEvent(begin:2)]
let se = StatusEvent(begin:1)
if find(arr,se) == nil { // not already present
    arr.append(se)
    arr.sort(<)
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Even if you decide to go with a binary search instead of sorting, making StatusEvent a Comparable is probably going to save you some work. – matt May 15 '15 at 16:20
  • "First of all, in Swift, if you have no good reason to make something a class, make it a struct..." Can I ask why? I would have thought just the opposite? What would be the reasons? If it's in your book already... I have it, just give me a page number. :) – Travis Griggs May 15 '15 at 17:32
  • 1
    It is, but I'll just summarize :) struct is the Swift object type par excellence. class adds a bunch of heavyweight stuff (inheritance) plus it turns this thing into a reference type instead of a value type (big memory management complications), and I don't see you using any of that, so a struct seems more appropriate. – matt May 15 '15 at 17:38