Коротка інформація: Багато (більшість?) Сучасних мов програмування, що широко використовуються, мають принаймні декілька спільних ADT (абстрактних типів даних), зокрема,
рядок (послідовність, що складається з символів)
список (упорядкована колекція значень) та
тип на основі карти (не упорядкований масив, який відображає ключі до значень)
У мові програмування R перші два реалізовані як characterі vector, відповідно.
Коли я почав вивчати R, дві речі були очевидні майже з самого початку: listце найважливіший тип даних в R (адже це батьківський клас для R data.frame), а по-друге, я просто не міг зрозуміти, як вони працюють недостатньо добре, щоб правильно їх використовувати в коді.
По-перше, мені здалося, що listтип даних R - це пряма реалізація карти ADT ( dictionaryв Python, NSMutableDictionaryв Objective C, hashPerl і Ruby, object literalу Javascript тощо).
Наприклад, ви створюєте їх так само, як і словник Python, передаючи парам ключ-значення конструктору (що в Python dictне є list):
x = list("ev1"=10, "ev2"=15, "rv"="Group 1")
І доступ до елементів зі списку R, як ви б ті з словника Python, наприклад, x['ev1']. Так само ви можете отримати лише "ключі" або просто "значення" за допомогою:
names(x) # fetch just the 'keys' of an R list
# [1] "ev1" "ev2" "rv"
unlist(x) # fetch just the 'values' of an R list
# ev1 ev2 rv
# "10" "15" "Group 1"
x = list("a"=6, "b"=9, "c"=3)
sum(unlist(x))
# [1] 18
але R lists також не схожі на інші рекламні картки типу (серед мов, яких я навчився в будь-якому випадку). Я здогадуюсь, що це наслідок початкової специфікації для S, тобто наміру створити DSL даних / статистики [мова, що залежить від домену] з нуля.
три суттєві відмінності між listтипами R s та картографуванням в інших мовах при широкому використанні (наприклад, Python, Perl, JavaScript):
по-перше , lists в R - це впорядкована колекція, подібно до векторів, навіть незважаючи на те, що значення клавішуються (тобто, ключі можуть бути будь-якими хешируемыми значеннями, а не лише послідовними цілими числами). Майже завжди тип даних відображення в інших мовах є не упорядкованим .
по-друге , lists може бути повернуто з функцій, навіть якщо ви ніколи не переходили в a, listколи ви викликали функцію, і навіть незважаючи на те, що функція, яка повертається list, не містить (явного) listконструктора (Звичайно, ви можете вирішити це на практиці, завершення повернутого результату в дзвінок до unlist):
x = strsplit(LETTERS[1:10], "") # passing in an object of type 'character'
class(x) # returns 'list', not a vector of length 2
# [1] list
Третя особливість R - х listроків: це не здається , що вони можуть бути членами іншого ADT, і якщо ви спробуєте зробити це , то первинний контейнер примушують до list. Наприклад,
x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)
class(x)
# [1] list
мій намір тут не критикувати мову чи те, як це задокументовано; так само, я не припускаю, що в listструктурі даних чи тому, як вона поводиться, щось не так . Я лише хочу виправити своє розуміння того, як вони працюють, щоб я міг правильно використовувати їх у своєму коді.
Ось такі речі, які я хотів би краще зрозуміти:
Які правила визначають, коли виклик функції поверне a
list(наприклад,strsplitвираз, прочитаний вище)?Якщо я не призначаю явно імена
list(наприклад,list(10,20,30,40)) - це імена за замовчуванням лише послідовні цілі числа, що починаються з 1? (Я припускаю, але я далеко не впевнений, що відповідь "так", інакше ми б не змогли примусити цей типlistдо вектору без викликуunlist.)Чому ці два різні оператори
[]і[[]]повертають один і той же результат?x = list(1, 2, 3, 4)обидва вирази повертають "1":
x[1]x[[1]]чому ці два вирази не повертають однакового результату?
x = list(1, 2, 3, 4)x2 = list(1:4)
Будь ласка, не вказуйте мені на Документацію R ( ?list, R-intro) - я її уважно прочитав, і це не допомагає мені відповісти на тип запитань, які я декламував вище.
(нарешті, я нещодавно дізнався про це і почав використовувати пакет R (доступний на CRAN), hashякий називається, що реалізує звичайну поведінку типу карт через клас S4; я, безумовно, рекомендую цей пакет.)
listв R не схожі на хеш. У мене є ще один, який я вважаю гідним відзначити. listв R може бути два члени з однаковим довідковим іменем. Вважайте, що obj <- c(list(a=1),list(a=2))це дійсно, і повертає список з двома названими значеннями 'a'. У цьому випадку виклик для obj["a"]поверне лише перший елемент відповідного списку. Ви можете отримати поведінку, схожу (можливо ідентичну) хешу, лише з одним елементом на x <- new.env(); x[["a"]] <- 1; x[["a"]] <- 2; x[["a"]]
x = list(1, 2, 3, 4), обидва вони НЕ повертають однаковий результат:,x[1]іx[[1]]. Перший повертає список, а другий повертає числовий вектор. Прокручуючи нижче, мені здається, що Дірк був єдиним респондентом, який правильно вирішив це питання.