Latar belakang singkat: Banyak (kebanyakan?) Bahasa pemrograman kontemporer yang digunakan secara luas memiliki setidaknya beberapa ADT [tipe data abstrak] yang sama, khususnya,
string (urutan terdiri dari karakter)
daftar (koleksi nilai yang dipesan), dan
tipe berbasis peta (array tidak berurutan yang memetakan kunci nilai)
Dalam bahasa pemrograman R, dua yang pertama diimplementasikan sebagai character
dan vector
, masing-masing.
Ketika saya mulai belajar R, dua hal sudah jelas hampir dari awal: list
adalah tipe data yang paling penting dalam R (karena itu adalah kelas induk untuk R data.frame
), dan kedua, saya tidak bisa mengerti bagaimana mereka bekerja, setidaknya tidak cukup baik untuk menggunakannya dengan benar dalam kode saya.
Untuk satu hal, menurut saya list
tipe data R adalah implementasi langsung dari peta ADT ( dictionary
dalam Python, NSMutableDictionary
di Objective C, hash
di Perl dan Ruby, object literal
di Javascript, dan sebagainya).
Misalnya, Anda membuatnya sama seperti kamus Python, dengan meneruskan pasangan nilai kunci ke konstruktor (yang dalam Python dict
tidak list
):
x = list("ev1"=10, "ev2"=15, "rv"="Group 1")
Dan Anda mengakses item dari Daftar R sama seperti Anda dengan orang-orang dari kamus Python, misalnya x['ev1']
,. Demikian juga, Anda dapat mengambil hanya 'kunci' atau hanya 'nilai' dengan:
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
tetapi R list
juga tidak seperti ADT tipe peta lainnya (dari antara bahasa yang saya pelajari). Dugaan saya adalah bahwa ini adalah konsekuensi dari spesifikasi awal untuk S, yaitu niat untuk merancang data / statistik DSL [bahasa khusus domain] dari bawah ke atas.
tiga perbedaan signifikan antara R list
s dan tipe pemetaan dalam bahasa lain dalam penggunaan luas (mis., Python, Perl, JavaScript):
pertama , list
s dalam R adalah koleksi yang diurutkan , seperti vektor, meskipun nilainya dikunci (yaitu, kunci dapat berupa nilai hashable bukan hanya bilangan bulat berurutan). Hampir selalu, tipe data pemetaan dalam bahasa lain tidak berurutan .
kedua , list
s dapat dikembalikan dari fungsi meskipun Anda tidak pernah melewati list
ketika Anda memanggil fungsi, dan meskipun fungsi yang mengembalikan list
tidak mengandung list
konstruktor ( eksplisit) (Tentu saja, Anda dapat menangani ini dalam praktik dengan membungkus hasil yang dikembalikan dalam panggilan ke 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
Sebuah ketiga fitur khas R list
s: itu tidak tampak bahwa mereka dapat menjadi anggota ADT lain, dan jika Anda mencoba untuk melakukan itu maka wadah primer dipaksa untuk list
. Misalnya,
x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)
class(x)
# [1] list
maksud saya di sini bukan untuk mengkritik bahasa atau bagaimana bahasa itu didokumentasikan; juga, saya tidak menyarankan ada yang salah dengan list
struktur data atau bagaimana perilakunya. Yang saya cari hanyalah mengoreksi pemahaman saya tentang cara kerjanya sehingga saya dapat menggunakannya dengan benar dalam kode saya.
Berikut adalah beberapa hal yang saya ingin lebih mengerti:
Apa aturan yang menentukan kapan pemanggilan fungsi akan mengembalikan
list
(misalnya,strsplit
ekspresi dilafalkan di atas)?Jika saya tidak secara eksplisit menetapkan nama ke
list
(misalnya,list(10,20,30,40)
) apakah nama default hanyalah bilangan bulat berurutan yang dimulai dengan 1? (Saya berasumsi, tapi saya jauh dari yakin bahwa jawabannya adalah ya, kalau tidak kita tidak akan bisa memaksa jenis inilist
ke vektor dengan panggilanunlist
).Mengapa dua operator yang berbeda ini
[]
,, dan[[]]
, mengembalikan hasil yang sama ?x = list(1, 2, 3, 4)
kedua ekspresi menghasilkan "1":
x[1]
x[[1]]
mengapa kedua ungkapan ini tidak memberikan hasil yang sama?
x = list(1, 2, 3, 4)
x2 = list(1:4)
Tolong jangan arahkan saya ke Dokumentasi R ( ?list
, R-intro
) - Saya telah membacanya dengan seksama dan itu tidak membantu saya menjawab jenis pertanyaan yang saya baca di atas.
(terakhir, saya baru-baru ini belajar dan mulai menggunakan Paket R (tersedia di CRAN) yang disebut hash
yang mengimplementasikan perilaku tipe peta konvensional melalui kelas S4; Saya pasti dapat merekomendasikan Paket ini.)
list
di R tidak seperti hash. Saya punya satu lagi yang menurut saya layak untuk dicatat. list
di R dapat memiliki dua anggota dengan nama referensi yang sama. Pertimbangkan itu obj <- c(list(a=1),list(a=2))
valid dan mengembalikan daftar dengan dua nilai bernama 'a'. Dalam hal ini panggilan untuk obj["a"]
hanya akan mengembalikan elemen daftar pencocokan pertama. Anda bisa mendapatkan perilaku yang mirip (mungkin identik) dengan hash dengan hanya satu item per nama yang direferensikan menggunakan lingkungan dalam R. misalnyax <- new.env(); x[["a"]] <- 1; x[["a"]] <- 2; x[["a"]]
x = list(1, 2, 3, 4)
, keduanya TIDAK mengembalikan hasil yang sama:,x[1]
danx[[1]]
. Yang pertama mengembalikan daftar dan yang kedua mengembalikan vektor numerik. Dengan menggulir ke bawah, saya melihat bahwa Dirk adalah satu-satunya responden yang menjawab pertanyaan ini dengan benar.