2014-12-29 5 views
1

R을 사용하여 큰 JS 개체 (라이브러리 rjsonio 사용)로 작업하고 있습니다. 따라서 중첩 목록이 많아서 작업하기가 다소 번거롭습니다. 아래에 간단한 예제가 있습니다. 나는 'getter'와 'setter'함수의 어떤 형태를 만들어서이 객체로 작업하려고 노력하고있다. 둘러보고 난 후에, 나는 객체를 재귀하고 첫 번째로 일치하는 레이블을 반환하는 꽤 좋은 'getter'함수를 발견했다. 이것은 함수를 연결하는 데 적합하기 때문에 특히 좋습니다. 그러나, 나는 'setter'기능에 대해 동일한 효과를 얻는 방법을 이해할 수 없다. 유사한 방식으로 함께 묶일 수있는 '세터'기능을 만드는 방법에 대한 의견이 있으십니까?여러 대체 함수 연결 R

#example, simplified, object 
app = list(
    1, 
    2, 
    d=list(a=123, 
     b=456, 
     list(
      FirstKey=list(attr1='good stuff', attr2=12345), 
      SecondKey=list(attr1='also good stuff', attr2=4321) 
      ) 
     ) 
) 


#Return a function that returns the value 
#associated with first label that matches 'name' 
getByName <- function(name){ 
    rmatch <- function(x) { 
    pos <- match(name, names(x)) 
    if (!is.na(pos)) 
     return(x[[pos]]) 
    for (el in x) { 
     if (class(el) == "list") { 
     out <- Recall(el) 
     if (!is.null(out)) return(out) 
     } 
    } 
    } 
    rmatch 
} 

getFirstKey <- getByName("FirstKey") 
getAttr1 <- getByName("attr1") 
getAttr2 <- getByName("attr2") 

#I like that I can chain these functions together 
getAttr1(getFirstKey(app)) 
getAttr2(getFirstKey(app)) 

# I would like to be able to do something like this 
# But this won't work 
### getAttr1(getFirstKey(app)) <- 9876 

# This does work,,, but I loose the ability to chain functions together 
# Closure around a replacement function 
setterKeyAttr <- function(keyName, attr){ 
    function(x, value){ 
    x$d[[3]][[keyName]][[attr]] <- value 
    x 
    } 
} 

`setFirstKeyAttr2<-` <- setterKeyAttr("FirstKey", "attr2") 
setFirstKeyAttr2(app) <- 22222 
#check the answer is correct 
getAttr2(getFirstKey(app)) 

참조 : R decorator to change both input and output

http://r.789695.n4.nabble.com/How-to-get-a-specific-named-element-in-a-nested-list-td3037430.html

http://adv-r.had.co.nz/Functions.html

답변

0

이 내가 생각 해낸 것입니다. 재귀 함수가 '이름'의 위치를 ​​반환하고 여전히 호출을 함께 연결할 수 있습니다. 이것이 좋은 방법인지 확실하지 않지만 ... 작동하는 것처럼 보입니다 ... 이것은 app [[c (3,3,1,)]]이 유효한 방법이라는 사실을 기반으로합니다. R로 색인하는 방법

rmatch.pos <- function(object, name, seq=NA, level=NULL){ 
    ##return the vector of integers corresponding to the first match 
    ##of 'name' to a label in object or NULL if no match is found 
    ###object: a list, likely deeply nested 
    ##name: the name of the label to look for 
    ##seq: starting point to search for 'name' in 'object' i.e. c(2,3,3) 
    ##level: don't touch this; it keeps track of how deep the recursive execution is 
    ##can be chained together to reduce ambiguity or result: 
    ##obj <- list(a=1, b=list(c=2, d=list(e=1, attr1="really?", f=list(attr1 = "found me!")))) 
    ##obj[[rmatch.pos(obj, "attr1", rmatch.pos(obj, "f"))]] 

    if(is.null(seq)){ 
    #short circuit if NULL gets passed 
    #when chaining, this forces the whole 'chain' 
    #to NULL when any 'link' is NULL 
    return(NULL) 
    } 
    if(is.null(level)){ 
    level <- length(na.omit(seq)) 
    } 
    if(any(is.na(seq))){ 
    temp <- object 
    }else{ 
    temp <- object[[seq]] 
    } 
    level <- level + 1 
    pos <- match(name, names(temp)) 
    if(!is.na(pos)){ 
    seq[level] <- pos 
    return(seq) 
    } 
    for(el in seq_along(temp)){ 
    if(class(temp[[el]]) == "list"){ 
     seq[level] <- el 
     out <- Recall(object, name, seq, level) 
     if(!is.null(out)){ 
     return(out) 
     } 
    } 
    } 
} 


###Examples 
rmatch.pos(app, "ThirdKey") 
rmatch.pos(app, "attr2") 
###chaining example 
rmatch.pos(app, "attr2", rmatch.pos(app, "FirstKey")) 
rmatch.pos(app, "attr2", rmatch.pos(app, "SecondKey")) 
rmatch.pos(app, "attr1", rmatch.pos(app, "ERROR")) 
rmatch.pos(app, "ERROR", rmatch.pos(app, "attr1"))