พื้นหลังโดยย่อ: ภาษาการเขียนโปรแกรมร่วมสมัยส่วนใหญ่ (มากที่สุด) ที่ใช้กันอย่างแพร่หลายมีอย่างน้อยหนึ่ง ADTs [ประเภทข้อมูลนามธรรม] โดยทั่วไปโดยเฉพาะ
สตริง (ลำดับประกอบด้วยอักขระ)
รายการ (ชุดของค่าสั่ง) และ
ชนิดที่ยึดตามแผนที่ (อาร์เรย์ที่ไม่ได้เรียงลำดับที่จับคู่คีย์กับค่า)
ในภาษาการเขียนโปรแกรม R ทั้งสองจะถูกนำมาใช้เป็นcharacter
และvector
ตามลำดับ
เมื่อฉันเริ่มเรียนรู้ R มีสองสิ่งที่เห็นได้ชัดเจนตั้งแต่เริ่มต้น: list
เป็นประเภทข้อมูลที่สำคัญที่สุดใน R (เพราะเป็นคลาสผู้ปกครองสำหรับ R data.frame
) และที่สองฉันไม่เข้าใจวิธีการทำงานอย่างน้อย ไม่ดีพอที่จะใช้อย่างถูกต้องในรหัสของฉัน
สำหรับสิ่งหนึ่งที่ดูเหมือนว่าlist
ประเภทข้อมูลของ R คือการใช้แผนที่ ADT ( dictionary
ใน Python, NSMutableDictionary
Objective C, hash
Perl และ Ruby, object literal
Javascript และอื่น ๆ )
ตัวอย่างเช่นคุณสร้างพวกเขาเช่นเดียวกับที่คุณทำกับพจนานุกรม Python โดยส่งผ่านคู่ของคีย์ - ค่าไปยังตัวสร้าง (ซึ่งใน Python dict
ไม่ใช่list
):
x = list("ev1"=10, "ev2"=15, "rv"="Group 1")
และคุณเข้าถึงรายการของ R 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 list
s ก็ไม่เหมือนกับ ADT ประเภทแผนที่อื่น ๆ (จากภาษาที่ฉันได้เรียนรู้อยู่แล้ว) ฉันเดาว่านี่เป็นผลมาจากสเป็คเริ่มต้นสำหรับ S คือความตั้งใจในการออกแบบข้อมูล / สถิติ DSL [ภาษาเฉพาะโดเมน] จากพื้นฐาน
สามความแตกต่างที่สำคัญระหว่าง R list
s และประเภทการแมปในภาษาอื่น ๆ ที่ใช้กันอย่างแพร่หลาย (เช่น Python, Perl, JavaScript):
ครั้งแรก , list
s ใน R เป็นสั่งซื้อคอลเลกชันเช่นเดียวกับเวกเตอร์แม้ว่าค่าที่มีความสำคัญ (เช่นปุ่มจะถูกจำนวนเต็มค่า hashable ใด ๆ ที่ไม่ได้เป็นเพียงตามลำดับ) เกือบทุกชนิดข้อมูลแผนที่ในภาษาอื่น ๆเรียงลำดับ
สอง , list
s สามารถกลับมาจากการทำงานแม้ว่าคุณจะไม่เคยผ่านใน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
สามคุณลักษณะเฉพาะของอาร์เอสlist
S: มันไม่ได้ดูเหมือนว่าพวกเขาสามารถเป็นสมาชิกของ 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]]
รายการแรกส่งคืนรายการและรายการที่สองส่งคืนค่าเวกเตอร์เป็นตัวเลข เมื่อเลื่อนด้านล่างฉันเห็นว่าเดิร์คเป็นผู้ตอบเพียงคนเดียวที่ตอบคำถามนี้อย่างถูกต้อง