แผนที่ฟังก์ชั่นในรายการทรัพย์สินหรือไม่


17

ถาม:วิธีการแมปฟังก์ชันใดในรายการคุณสมบัติคืออะไร

ฟังก์ชั่นการทำแผนที่ต่างๆ ( mapcarและครอบครัว) แมปฟังก์ชั่นมากกว่าลำดับเช่นรายการ เราจะใช้ฟังก์ชั่นเหล่านี้เมื่อจัดการกับรายการคุณสมบัติได้อย่างไรเช่นเมื่อพยายามแมปกับคุณสมบัติแต่ละรายการที่มีอยู่ในรายการ (ซึ่งจะเป็นองค์ประกอบอื่น ๆ ที่เริ่มต้นจากองค์ประกอบแรก) สำหรับผมแล้วดูเหมือนว่าฟังก์ชั่นการแมปจะต้องเข้าถึงรายการในคู่ขององค์ประกอบมากกว่าเป็นองค์ประกอบของแต่ละบุคคล

ในฐานะที่เป็นตัวอย่างของเล่นคนหนึ่งจะใช้รายการทรัพย์สินและรวบรวมค่าคุณสมบัติทั้งหมดได้อย่างไร ถ้ามันเป็นรายการเชื่อมโยงแทนมันจะค่อนข้างง่าย:

(mapcar #'cadr '((:prop1 a) (:prop2 b) (:prop3 c))) ;=> (a b c)

ฉันแน่ใจว่าสิ่งนี้สามารถทำได้ด้วยการวนรอบ แต่ดูเหมือนว่าจะลำบากเล็กน้อยและฉันสงสัยว่ามีวิธีใช้สำนวนมากกว่านี้หรือไม่


โปรดระบุว่าคุณต้องการแมปเฉพาะค่าของคุณสมบัติ (ซึ่งเป็นสิ่งที่ดูเหมือนและเป็นmapcarตัวอย่างของalist ของคุณหรือไม่) หรือคุณต้องการแมปผ่านคู่ของสัญลักษณ์คุณสมบัติและค่าคุณสมบัติ หลังมีทั่วไปมากขึ้น (มีประโยชน์มากกว่าโดยทั่วไป) ฉันเดา
ดึง

@ ดึง: ฉันสนใจมากขึ้นในกรณีทั่วไป; ตัวอย่างคือสิ่งที่ง่ายที่สุดที่ฉันนึกได้ ผมอยากจะทราบวิธีการ map เหนือทรัพย์สิน / ค่าคู่ ถ้าคำตอบคือ "a loop" งั้นก็เถอะ แต่ฉันสงสัยว่ามันมีทางออกที่ดีกว่านี้ไหม
แดน

สิ่งที่คุณมีในตัวอย่างไม่ใช่รายการอสังหาริมทรัพย์ รายการคุณสมบัติมีจำนวนคู่ขององค์ประกอบองค์ประกอบคี่เป็นชื่อคุณสมบัติแม้องค์ประกอบเป็นค่าคุณสมบัติ สิ่งที่คุณอาจจะเรียกว่าทรี (รายการของรายการ)
wvxvw

คำตอบ:


8

คุณอาจได้loopรับคำตอบที่หลากหลายและซ้ำ AFAIK ไม่มีวิธีที่จะทำสิ่งนี้ ฉันไม่คิดว่ามันเป็นเรื่องธรรมดามากที่จะต้องการสะสมเฉพาะค่าคุณสมบัติ (ไม่เชื่อมโยงกับคุณสมบัติ)

นี่คือวิธีง่ายๆในการทำ:

(defun prop-values (plist)
  "..."
  (let ((pl    (cdr plist))
        (vals  ()))
    (while pl
      (push (car pl) vals)
      (setq pl  (cddr pl)))
    (nreverse vals)))

สำหรับกรณีทั่วไปมากขึ้นซึ่งคุณต้องการแมปฟังก์ชันไบนารีบนเพลต:

(defun map-plist (fn plist)
  "..."
  (let ((pl    plist)
        (vals  ()))
    (while pl
      (push (funcall fn (car pl) (cadr pl)) vals)
      (setq pl (cddr pl)))
    (nreverse vals)))

(setq foo '(a 1 b 2 c 3 d 4 e 5))

(map-plist #'cons foo) ; => ((a . 1) (b . 2) (c . 3) (d . 4) (e . 5))

13

สิ่งนี้อาจขึ้นอยู่กับสถานการณ์ โดยทั่วไปถ้าฉันต้องผูกจำนวนของค่ากับจำนวนของชื่อฉันต้องการใช้กัญชาตาราง cl-loopแต่ถ้าผมต้องใช้รายการทรัพย์สินฉันต้องการใช้ ด้านล่างเป็นตัวอย่าง:

(cl-loop for (key value) on '(:prop1 a :prop2 b :prop3 c) by 'cddr
         collect value)
;;; (a b c)

และถ้าคุณมีโครงสร้างข้อมูลที่คุณแสดงในตัวอย่างของคุณ:

(cl-loop for (key value) in '((:prop1 a) (:prop2 b) (:prop3 c))
         collect value)
;;; (a b c)

5

สำหรับฉันคำตอบคือเปลี่ยนคำให้เป็นอลิสต์ซึ่งเป็นโครงสร้างข้อมูลที่เทียบเท่าเพียงครึ่งหนึ่งที่ลึกและง่ายต่อการจัดการ


3
นั่นเป็นคำตอบที่ดี (และคำแนะนำที่ดี) แต่มีความคิดเห็นมากกว่า
ดึง

4

ด้วย Emacs จากปัจจุบัน Git HEAD ซึ่งจะกลายเป็น Emacs 25 คุณสามารถทำต่อไปนี้คือเปิด plist เข้า alist ได้อย่างง่ายดายด้วยใหม่ seq-partitionฟังก์ชั่นและจากนั้นประมวลผลรายการ alist mapcarโดยใช้มาตรฐาน

(let* ((my-plist (list :a 1 :b 2 :c 3 :more (list 4 5 6)))
       (my-alist (seq-partition my-plist 2))
       (my-reverse-alist (mapcar (lambda (entry)
                                   (let ((prop (car entry))
                                         (val  (cadr entry)))
                                     (list val prop)))
                                 my-alist)))
  (message "my-plist: %s\nmy-alist: %s\nmy-reverse-alist: %s"
           my-plist my-alist my-reverse-alist))
;; my-plist: (:a 1 :b 2 :c 3 :more (4 5 6))
;; my-alist: ((:a 1) (:b 2) (:c 3) (:more (4 5 6)))
;; my-reverse-alist: ((1 :a) (2 :b) (3 :c) ((4 5 6) :more))

มีรูปลักษณ์ที่เอกสารโดยใช้seq-partitionC-h f seq-partition RET


1

แนวคิดหนึ่งคือใช้-map-indexedจากdashและใช้การแปลงกับค่าคี่ของรายการเท่านั้น:

(-non-nil (-map-indexed (lambda (index item) (when (oddp index) item))
  '(a x b y c z))) ; => (x y z)
(-non-nil (--map-indexed (when (oddp it-index) it) '(a x b y c z))) ; => (x y z)

อีกแนวคิดหนึ่งคือเพียงแปลง plist เป็น hash-table โดยใช้ht<-plistจากht:

(ht-values (ht<-plist '(a x b y c z) 'equal)) ; (z y x)

โปรดสังเกตว่าแฮชตารางไม่รักษาลำดับของรายการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.