Idiomatic go way to compare 2 slices to see which element has been removed -
i using rethinkdb in application , have lobby has users.
rethinkdb has ability watch changes table , when changes happen automagically emits changes can whatever want data, right i'm trying make when user leaves lobby can send websocket out remove user. thing i'm trying find out difference in before / after data slice of members, data:
type change struct { newval *fields `gorethink:"new_val,omitempty"` oldval *fields `gorethink:"old_val,omitempty"` } type fields struct { id string `gorethink:"id"` owner string `gorethink:"owner"` inqueue bool `gorethink:"inqueue"` members []struct { steamid string `gorethink:"steamid"` username string `gorethink:"username"` } `gorethink:"members"` messages []struct { username string `gorethink:"username"` message string `gorethink:"message"` createdat time.time `gorethink:"createdat"` } `gorethink:"messages"` } right i'm doing
func (l *lobby) watchchanges() { db := common.db() query := gorethink.table("lobbys").get(l.id).changes() res, err := query.run(db) if err != nil { log.println(err) } go func(res *gorethink.cursor, l *lobby) { defer res.close() changes := new(change) res.next(&changes) { if changes.newval != nil && changes.oldval != nil { switch { case len(changes.newval.members) > len(changes.oldval.members): // member has joined announce was. case len(changes.newval.members) < len(changes.oldval.members): // member has left announce was. --------> case len(changes.newval.messages) > len(changes.oldval.messages): // new message recieved announce message. } } } }(res, l) select { case <-l.killme: res.close() break } } the new entries easy enough i'll take end off slice , send that, when comes user leaving, how can compare changes.newval.members , changes.oldval.members see index removed can send right member remove through websocket. hope question clear let me know if isn't.
this how i'm doing it
removedindex := 0 i, oldmember := range changes.oldval.members { foundmissing := true _, newmember := range changes.newval.members { if reflect.deepequal(oldmember, newmember) { foundmissing = false } } if foundmissing { removedindex = break } } but feels bit hacky, there better way?
sort old , new members unique , sortable key. looks steamid might suitable purpose. iterate through both slices checking added , deleted elements comparing keys.
func diff(old []*member, new []*member) { sort.sort(bysteamid(old)) sort.sort(bysteamid(new)) i, j := 0, 0 < len(old) && j < len(new) { switch { case old[i].steamid < new[j].steamid: fmt.println(" delete", old[i].steamid) i++ case old[i].steamid > new[j].steamid: fmt.println(" add", new[j].steamid) j++ default: i++ j++ } } < len(old) { fmt.println(" delete", old[i].steamid) i++ } j < len(new) { fmt.println(" add", new[j].steamid) j++ } }
Comments
Post a Comment