Как мне использовать декларативный подход для необязательного добавления элемента в список в R? - PullRequest
0 голосов
/ 02 мая 2019

Я имею дело с json и обнаружил, что использование списков великолепно, так что я могу использовать Map и еще много чего. Это более декларативный подход, но я не могу найти хорошее решение для необязательного добавления элемента списка.

Вложенный список (то есть стиль "list (list (...))") необходим для создания json, который требуется API.

library(jsonlite)

# optionally add mydoc
mydoc <- NULL # mydoc <- 1

jelist <- list(
  JournalEntry = list(
    list(
      trxdate = '2019-01-01',
      docnum = mydoc,
      line = list(
        # 2 lines for 1 dr and 1 cr
        list(
          debitcredit = 'debit',
          accountref = 1
        ),
        list(
          debitcredit = 'credit',
          accountref = 2
        )
      )
    )
  )
)

# it's added when I don't want it
toJSON(jelist,pretty = T,auto_unbox = T)

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

jelist$JournalEntry[[1]]$docnum <- NULL

# correct output    
toJSON(jelist,pretty = T,auto_unbox = T)

быстрое упрощение для остальных примеров

Сохранение этого может предотвратить ложноположительные решения, которые могут обрабатывать простые списки, но не вложенные списки.

linelist <- list(
  # 2 lines for 1 dr and 1 cr
  list(
    debitcredit = 'debit',
    accountref = 1
  ),
  list(
    debitcredit = 'credit',
    accountref = 2
  )
)

вещи, которые я пробовал

установлен как ноль, NA, логический (0)

jelist <- list(
  JournalEntry = list(
    list(
      trxdate = '2019-01-01',
      docnum = NULL, # or NA or logical(0)
      line = linelist
    )
  )
)
toJSON(jelist,pretty = T,auto_unbox = T)

если stmt

jelist <- list(
  JournalEntry = list(
    list(
      trxdate = '2019-01-01',
      if(is.null(mydoc)){}else{docnum = mydoc}),
      line = linelist
    )
  )
toJSON(jelist,pretty = T,auto_unbox = T)

Фильтр

Я бы хотел, чтобы в любом случае я мог просто объявить его как встроенный, если я хочу, чтобы он был удален или нет. Что если я действительно хочу отправить NULL в качестве обновления?

jelist <- list(
  JournalEntry = list(
    list(
      trxdate = '2019-01-01',
      docnum = mydoc,
      line = linelist
    )
  )
)
toJSON(Filter(Negate(is.null),jelist),pretty = T,auto_unbox = T)

возиться с c, списком и т. Д.

jelist <- list(
  JournalEntry = list(
    list(
      trxdate = '2019-01-01',
      as.list(c(docnum = NULL)),
      line = linelist
    )
  )
)
toJSON(jelist,pretty = T,auto_unbox = T)

Я пробовал unlist / relist, но я не слишком знаком с их использованием. Опять же, надеясь, что я могу иметь его в строке. Попытался изменить списки на использование c () и as.list () с некоторыми многообещающими вещами, но безуспешно. Каким-то образом c () переименовывает мои 2 строки в Line1 и Line2.

Есть еще идеи?

1 Ответ

0 голосов
/ 02 мая 2019

plyr::compact удалит NULL из списков. По умолчанию он работает с уже созданным списком. Чтобы использовать его декларативно, вам нужно поднять свой домен из списка в точки.

mylist <- purrr::lift_ld( plyr::compact )

## For example,
mylist( a=1, b=NULL, c=3 )
# $a
# [1] 1
# 
# $c
# [1] 3

Теперь просто замените каждый вызов list() вызовом только что определенного mylist:

jelist <- mylist(
  JournalEntry = mylist(
    mylist(
      trxdate = '2019-01-01',
      docnum = mydoc,
      line = mylist(
        # 2 lines for 1 dr and 1 cr
        mylist(
          debitcredit = 'debit',
          accountref = 1
        ),
        mylist(
          debitcredit = 'credit',
          accountref = 2
        )
      )
    )
  )
)

toJSON(jelist, pretty = TRUE, auto_unbox = TRUE)   ## Works as desired
...