doupao1530 2016-01-06 02:35
浏览 18
已采纳

习惯用法比较2个切片以查看已删除哪个元素

I am using RethinkDB in my application and I have a lobby that has users.

RethinkDB has the ability to watch for changes to a table and when changes happen it automagically emits the changes so you can do whatever you want with the data, right now I'm trying to make it so when a user leaves the lobby I can send a websocket out to remove the user. The only thing is I'm trying to find out where the difference is in the before / after data which is a slice of members, this is the 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 now 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)
        for res.Next(&changes) {
            if changes.NewVal != nil && changes.OldVal != nil {
                switch {
                case len(changes.NewVal.Members) > len(changes.OldVal.Members):
                    // Member has joined so announce who it was.

                case len(changes.NewVal.Members) < len(changes.OldVal.Members):
                    // Member has left so announce who it was.
           -------->
                case len(changes.NewVal.Messages) > len(changes.OldVal.Messages):
                    // New Message was recieved so announce the message.

                }
            }
        }
    }(res, l)

    select {
    case <-l.KillMe:
        res.Close()
        break
    }
}

The new entries are easy enough I'll just take the end off the slice and send that, but when it comes to the user leaving, how can I compare the changes.NewVal.Members and changes.OldVal.Members to see which index was removed so I can send the right member to remove through the websocket. Hope my question is clear let me know if it isn't.

This is how I'm currently doing it

removedIndex := 0
for i, oldMember := range changes.OldVal.Members {
    foundMissing := true
    for _, newMember := range changes.NewVal.Members {
        if reflect.DeepEqual(oldMember, newMember) {
            foundMissing = false
        }
    }
    if foundMissing {
        removedIndex = i
        break
    }
}

but it feels a bit hacky, is there a better way?

  • 写回答

1条回答 默认 最新

  • duandou8457 2016-01-06 03:03
    关注

    Sort the old and new members by a unique and sortable key. It looks like SteamID might be suitable for this purpose. Iterate through both slices checking for added and deleted elements by comparing the keys.

    func diff(old []*member, new []*member) {
      sort.Sort(bySteamID(old))
      sort.Sort(bySteamID(new))
      i, j := 0, 0
      for i < 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++
        }
      }
      for i < len(old) {
        fmt.Println(" delete", old[i].SteamID)
        i++
      }
      for j < len(new) {
        fmt.Println(" add", new[j].SteamID)
        j++
      }
    }
    

    <kbd>playground example</kbd>

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮