Нерекурсивная версия modifyList? - PullRequest
2 голосов
/ 01 мая 2020

Поведение modifyList заключается в рекурсивном изменении списков, т. Е. В этом случае fixed является вложенным списком, который также будет «изменен»:

default.options <- list(a = 1, b = 2, c = "hello", fixed = list(a = 1))
user.options <- list(b = 3, e = 0, fixed = list())

opts <- modifyList(default.options, user.options)
dput(opts)
# list(a = 1, b = 3, c = "hello", fixed = list(a = 1), e = 0)

Но что если Я не хочу, чтобы он следовал за подсписком fixed рекурсивно, а просто заменил его целиком, т.е. желаемый результат - это? :

list(a = 1, b = 3, c = "hello", fixed = list(), e = 0)

Есть ли простой способ сделать это нерекурсивное изменение списка?

Ответы [ 2 ]

3 голосов
/ 01 мая 2020

Вы можете просто сделать:

default.options[names(user.options)] <- user.options

identical(default.options, list(a = 1, b = 3, c = "hello", fixed = list(), e = 0))
[1] TRUE
2 голосов
/ 01 мая 2020

Мне кажется, простой ответ - просто скопировать и изменить исходный код modfiyList(), чтобы удалить его рекурсивную часть:

modify_list_nonrecursive <- function (x, val, keep.null = FALSE) {
    stopifnot(is.list(x), is.list(val))
    xnames <- names(x)
    vnames <- names(val)
    vnames <- vnames[nzchar(vnames)]
    if (keep.null) {
        for (v in vnames) {
            x[v] <-  val[v]
        }
    }
    else {
        for (v in vnames) {
            x[[v]] <- val[[v]]
        }
    }
    return(x)
}

default.options <- list(a = 1, b = 2, c = "hello", fixed = list(a = 1))
user.options <- list(b = 3, e = 0, fixed = list())

opts <- modifyList(default.options, user.options)
dput(opts)
# list(a = 1, b = 3, c = "hello", fixed = list(a = 1), e = 0)

opts <- modify_list_nonrecursive(default.options, user.options)
dput(opts)
# list(a = 1, b = 3, c = "hello", fixed = list(), e = 0)

Исходный код modifyList() был

modifyList

function (x, val, keep.null = FALSE) 
{
    stopifnot(is.list(x), is.list(val))
    xnames <- names(x)
    vnames <- names(val)
    vnames <- vnames[nzchar(vnames)]
    if (keep.null) {
        for (v in vnames) {
            x[v] <- if (v %in% xnames && is.list(x[[v]]) && is.list(val[[v]])) 
                list(modifyList(x[[v]], val[[v]], keep.null = keep.null))
            else val[v]
        }
    }
    else {
        for (v in vnames) {
            x[[v]] <- if (v %in% xnames && is.list(x[[v]]) && 
                is.list(val[[v]])) 
                modifyList(x[[v]], val[[v]], keep.null = keep.null)
            else val[[v]]
        }
    }
    x
}

Итак, вы можете видеть, что вам просто нужно удалить некоторые условные выражения с помощью рекурсивных вызовов, и все работает просто отлично!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...