Search code examples
rlistnested-lists

R Search for name in nested list and update the name


I have a nested list object cc. Within the nested list, I want to find if there is item named "StartDate" and update the name to "OccurrenceStartDate". Right now I am able to rapply to list the names and find the names and manually update. Is there a better way? I need to automate this process.

Also I need to update the format of the OccurrenceStartDate value. I am able to manually assign the format.

cc <- list(ConceptSets = list(list(id = 0L, name = "test cs", expression = list(
        items = list(list(concept = list(CONCEPT_ID = 1569193L, CONCEPT_NAME = "Cerebral infarction", 
                                         STANDARD_CONCEPT = "", STANDARD_CONCEPT_CAPTION = "", 
                                         INVALID_REASON = "V", INVALID_REASON_CAPTION = "Valid", 
                                         CONCEPT_CODE = "I63", DOMAIN_ID = "Condition", VOCABULARY_ID = "ICD10CM", 
                                         CONCEPT_CLASS_ID = "3-char nonbill code"), isExcluded = FALSE, 
                          includeDescendants = TRUE, includeMapped = FALSE))))), 
        PrimaryCriteria = list(CriteriaList = list(list(ConditionOccurrence = list(
            CodesetId = 0L, Age = list(Op = "eq", Value = 15L), StartDate = list(
                Op = "bt", Value = structure(17532, class = "Date"), 
                Extent = structure(18628, class = "Date"))))), ObservationWindow = list(
                    PriorDays = 0L, PostDays = 0L), PrimaryCriteriaLimit = list(
                        Type = "First")), QualifiedLimit = list(Type = "First"), 
        ExpressionLimit = list(Type = "First"), InclusionRules = list(), 
        CensoringCriteria = list(), CollapseSettings = list(CollapseType = "ERA", 
                                                            EraPad = 0L), CensorWindow = structure(list(), names = character(0)), 
        cdmVersionRange = ">=5.0.0")

    names(rapply(cc, function(x) head(x)))
    
    names(cc$PrimaryCriteria$CriteriaList[[1]]$ConditionOccurrence)[3] <- "OccurrenceStartDate"
    
    cc$PrimaryCriteria$CriteriaList[[1]]$ConditionOccurrence$OccurrenceStartDate$Value <- cc$PrimaryCriteria$CriteriaList[[1]]$ConditionOccurrence$OccurrenceStartDate$Value %>% format( "%m-%d-%Y")

This does not update the names but just lists the names

names(rapply(cc, function(x) head(x))) %>% str_replace_all(pattern = "StartDate","OccurrenceStartDate")

Solution

  • A solution with {data.tree}:

    library(data.tree)
    
    ## build tree from list:
    cc_tree <- FromListSimple(cc)
    
    ## update tree in place
    cc_tree$Do(function(node) node$name = gsub("StartDate", "OccurrenceStartDate", node$name)) 
    
    ## retransform tree to list:
    cc_renamed <- ToListSimple(cc_tree)
    
    ## > cc_renamed
    $name
    [1] "Root"
    
    $cdmVersionRange
    [1] ">=5.0.0"
    
    $ConceptSets
    $ConceptSets$name
    [1] "ConceptSets"
    
    ## ...
    
    $PrimaryCriteria$CriteriaList$`1`$ConditionOccurrence$OccurrenceStartDate
    $PrimaryCriteria$CriteriaList$`1`$ConditionOccurrence$OccurrenceStartDate$name
    
    ## ...