Comparing lists of lists effectively and only assigining those which differ

Hello,

I have these two lists called db1 and db2. db2 is the adjusted one after I have made changes and I want to update db1 without assigning db2 to db1 completely . Essentially, I want to only update the lists within the lists that differ between the two. There might be a point where the one is extraordinarily larger than the other (which my toy problem doesn't demonstrate) and I was just curious about best practices to update.

So in this example it should detect that v02 x is different along with v02 having z which did not exist for the other and then make those changes.

db1 <- 
  list(
    "id" = "id",
    "name" = "name",
    "owner" = "",
    "version" = list(
      "v01" = list("desc" = list("name" = "v01",
                                        "time" = Sys.time()),
                   "quest" = list(),
                   "x" = list(a = "a",b = "b",c = "c"),
                   "y" = list()),
      "v02" = list("desc" = list("name" = "v02",
                                        "time" = Sys.time()),
                   "quest" = list(),
                   "x" = list("b","e","f"),
                   "y" = list()))
  )

db2 <- 
  list(
    "id" = "id",
    "name" = "name",
    "owner" = "",
    "version" = list(
      "v01" = list("desc" = list("name" = "v01",
                                        "time" = Sys.time()),
                   "quest" = list(),
                   "x" = list(a = "a",b = "b",c = "c"),
                   "y" = list()),
      "v02" = list("desc" = list("name" = "v02",
                                        "time" = Sys.time()),
                   "quest" = list(),
                   "x" = list("a","b","c"),
                   "y" = list(),
                   "z" = list(1:10000)))
  )

Created on 2021-09-10 by the reprex package (v2.0.0)

library(tidyverse)

db1 <- 
  list(
    "id" = "id",
    "name" = "name",
    "owner" = "",
    "version" = list(
      "v01" = list("desc" = list("name" = "v01",
                                 "time" = Sys.time()),
                   "quest" = list(),
                   "x" = list(a = "a",b = "b",c = "c"),
                   "y" = list()),
      "v02" = list("desc" = list("name" = "v02",
                                 "time" = Sys.time()),
                   "quest" = list(),
                   "x" = list("b","e","f"),
                   "y" = list()))
  )

db2 <- 
  list(
    "id" = "id",
    "name" = "name",
    "owner" = "",
    "version" = list(
      "v01" = list("desc" = list("name" = "v01",
                                 "time" = Sys.time()),
                   "quest" = list(),
                   "x" = list(a = "a",b = "b",c = "c"),
                   "y" = list()),
      "v02" = list("desc" = list("name" = "v02",
                                 "time" = Sys.time()),
                   "quest" = list(),
                   "x" = list("a","b","c"),
                   "y" = list(),
                   "z" = list(1:10000)))
  )

iden <- map2_lgl(db1, db2, identical)
print(iden)
#>      id    name   owner version 
#>    TRUE    TRUE    TRUE   FALSE
db3 <- if_else(iden, db1, db2)

Created on 2021-09-10 by the reprex package (v1.0.0)

1 Like

Thanks for this reply! This is definitely already close to what I want. I see that when I compare db1 against db3 they are not identical given that the labels have vanished for id, name, owner etc. Is there some way to preserve this?

For some reason normal ifelse was fine. The solution above is working. Thanks again!

1 Like