R - Извлечение элементов из списка в соответствии с условием в `purrr ' - PullRequest
0 голосов
/ 15 июня 2019

У меня есть следующий список ввода HTML. Список имеет вложенную структуру -

  1. Уровень 1 содержит имена входов (например, input1).
  2. Уровень 2 содержит некоторую информацию о каждом входе - name, attribs, children
  3. Уровень 3 ответвляется от children, который представляет собой список длины 2 - первый элемент содержит информацию о метке ввода, а второй - информацию о типе ввода. Поскольку мне нужны метки ввода, мне нужно извлечь первый элемент этого списка для каждого ввода.

Список:

library(purrr)

inputs = list(
  input1 = list(
    name = 'div', 
    attribs = list(class = 'form-group'), 
    children = list(list(name = 'label', 
                         attribs = list(`for` = 'email'), 
                         children = list('Email')), 
                    list(
                      list(name = 'input', 
                           attribs = list(id = 'email', type = 'text'), 
                           children = list()))
                    )))

str(inputs)
List of 1
 $ input1:List of 3
  ..$ name    : chr "div"
  ..$ attribs :List of 1
  .. ..$ class: chr "form-group"
  ..$ children:List of 2
  .. ..$ :List of 3
  .. .. ..$ name    : chr "label"
  .. .. ..$ attribs :List of 1
  .. .. .. ..$ for: chr "email"
  .. .. ..$ children:List of 1
  .. .. .. ..$ : chr "Email"
  .. ..$ :List of 1
  .. .. ..$ :List of 3
  .. .. .. ..$ name    : chr "input"
  .. .. .. ..$ attribs :List of 2
  .. .. .. .. ..$ id  : chr "email"
  .. .. .. .. ..$ type: chr "text"
  .. .. .. ..$ children: list()

Я могу сделать это, используя keep() и has_element:

label = input %>% 
  map_depth(2, ~keep(., ~has_element(., 'label'))) %>%
  map('children') %>%
  flatten %>% 
  map('children') %>%
  flatten

Вывод:

str(label)
List of 1
 $ input1: chr "Email"

Когда я просматривал purrr справочные страницы, keep, казалось, был той функцией, за которой я следовал, но мне все равно приходилось дважды использовать map и flatten, чтобы добраться до метки, что выглядит неуклюже. Поэтому мне было интересно, есть ли более прямой способ добиться того же результата? Я не столько заинтересован в решении, сколько в мыслительном процессе работы с такими вложенными списками.

Ответы [ 2 ]

1 голос
/ 15 июня 2019

Если каждый вход имеет одинаковую структуру, тогда вам не нужен keep, который используется для удаления элементов списка, которые не удовлетворяют некоторым условиям.Вместо этого вы можете просто отобразить с помощью pluck, как это.Конечно, этот метод удаляет все остальные данные, относящиеся к каждому входу.Возможно, вы захотите сделать что-то другое, если конечной целью является «прямоугольник», то есть получение всей информации для каждого входа в плоской структуре.

library(purrr)

inputs = list(
  input1 = list(
    name = 'div', 
    attribs = list(class = 'form-group'), 
    children = list(
      list(
        name = 'label', 
        attribs = list(`for` = 'email'), 
        children = list('Email')
      ), 
      list(
        list(
          name = 'input', 
          attribs = list(id = 'email', type = 'text'), 
          children = list()
        )
      )
    )
  )
)

inputs %>%
  map(~ pluck(., "children", 1, "name"))
#> $input1
#> [1] "label"

Создано в 2019-06-14 с помощью Представить пакет (v0.3.0)

0 голосов
/ 15 июня 2019

Попробуйте:

map(inputs, "children") %>% map_depth(2, "children")

Вывод:

$input1
$input1[[1]]
$input1[[1]][[1]]
[1] "Email"


$input1[[2]]
NULL
...