ฉันจะแมปกับเวกเตอร์และรับเวกเตอร์ได้อย่างไร


15

สิ่งเดียวที่ฉันพบว่าทำงานได้คือ

(eval `(vector ,@(mapcar #'1+ [1 2 3 4])))
=> [2 3 4 5]

แต่ที่ดูเหมือนไกลซับซ้อนเกินไปที่จะเป็นขวา '' วิธี

คำตอบ:


19

ใช้cl-mapแทน:

(cl-map 'vector #'1+ [1 2 3 4])

พื้นหลังพิเศษเล็ก ๆ น้อย ๆ : cl-mapเป็นฟังก์ชั่นCommon LISPmapที่สรุปลักษณะของลำดับ:

(cl-map 'vector #'1+ '[1 2 3 4]) ;; ==> [2 3 4 5]
(cl-map 'list   #'1+ '(1 2 3 4)) ;; ==> (2 3 4 5)
(cl-map 'string #'upcase "abc")  ;; ==> "ABC"

นอกจากนี้ยังสามารถแปลงระหว่างประเภทลำดับ (เช่นที่นี่การป้อนข้อมูลเป็นรายการและการส่งออกเป็นเวกเตอร์):

(cl-map 'vector #'1+ '(1 2 3 4)) ;; ==> [2 3 4 5]

1
18 วินาทีผู้ชนะ ':) clห้องสมุดไม่ให้คำเตือนผู้แปล? (ส่วนใหญ่เป็นเพราะ FSF น่ารังเกียจ?)
Sean Allred

1
FWIW ฉันคิดว่าปัญหาการคอมไพล์ไบต์เกี่ยวข้องกับclไลบรารีเก่ามากกว่าcl-libไลบรารีrejiggered ฉันไม่ได้เช่นได้รับคำเตือนใด ๆ เมื่อฉันแล้ว(defun fnx () (cl-map 'vector #'1+ '[1 2 3 4])) (byte-compile 'fnx)
แดน

2
แม้ว่าคุณจะใช้ความเข้ากันได้ cl-lib ฉันคิดว่าคุณจะได้รับคำเตือนเกี่ยวกับ emacs รุ่นเก่า (24.2) ฉันไม่ต้องกังวลเกี่ยวกับมันแม้ว่าคุณจะต้องเลือกการต่อสู้ของคุณ
Malabarba

16

ตั้งแต่ฉันถูกตีด้วย 18 วินาทีนี่เป็นวิธีที่ง่ายและปลอดภัยกว่าในการทำโดยไม่ต้องใช้ห้องสมุด cl นอกจากนี้ยังไม่ได้ประเมินองค์ประกอบ

(apply #'vector (mapcar #'1+ [1 2 3 4])) ;; => [2 3 4 5]

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

1
ดีมาก !! applyฉันไม่คิดว่าเกี่ยวกับการใช้
Sean Allred

ผมคิดว่า(apply #'vector ...)อาจจะเคยให้เร็วขึ้นเล็กน้อย (vconcat ...)แต่เพื่อความสมบูรณ์ก็ยังสามารถถูกแทนที่ด้วย
เพรา

1

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

(setq x [1 2 3 4])

(cl-loop for var across-ref x do
         (setf var (1+ var)))

xผลที่ได้จะถูกเก็บไว้ใน หากคุณต้องการแบบฟอร์มที่จะส่งคืนxในที่สุดคุณสามารถเพิ่มfinally return xดังนี้:

(cl-loop for var across-ref x do
         (setf var (1+ var))
         finally return x)

1

เพื่อความสมบูรณ์โดยใช้seq:

(require 'seq)
(seq-into (seq-map #'1+ [1 2 3 4]) 'vector)

มีคำตอบที่ถูกลบจากFólkvangr 2018-11-12 ด้วยseq-intoบรรทัดเดียวกัน ผู้ใช้ลบคำตอบของเขาด้วยเหตุผลดังต่อไปนี้: "โซลูชันของฉันมีความเกี่ยวข้องน้อยลงเนื่องจากไลบรารี seq ใช้ส่วนขยาย Lisp ทั่วไป - Fólkvangr 16 พฤษภาคมเวลา 8:53 น."
Tobias

@Tobias ฉันคิดว่าฉันไม่เห็นด้วยกับตรรกะนั้น ทุกอย่างจะจบลงด้วยการใช้ vconcat หรือเวกเตอร์ แต่กระบวนทัศน์ส่วนต่อประสานที่แตกต่างกันนั้นมีประโยชน์ในการบันทึก
Sean Allred

ไม่มีปัญหา. ฉันเพิ่งเห็นคำตอบที่ถูกลบของFólkvangr (เกือบ) ที่ตรงกับคุณและต้องการแจ้งให้คุณทราบ ไม่ว่าด้วยเหตุผลใดก็ตามที่การดูคำตอบที่ถูกลบต้องใช้ 10,000 ตัวแทน :-(.
Tobias

@Tobias ใช่ฉันไม่เข้าใจจริงๆว่าทำไมสิทธิพิเศษเหล่านั้นเป็นเว็บไซต์ที่เฉพาะเจาะจง :-)
ฌอน Allred

0

คุณสามารถใช้วง

(let ((v (vector 1 2 3 4)))
  (dotimes (i (length v))
    (aset v i (1+ (aref v i))))
  v)
;; => [2 3 4 5]

บางครั้งคุณไม่ต้องการแก้ไขเวกเตอร์ดั้งเดิมคุณสามารถทำสำเนาได้

(let* ((v0 (vector 1 2 3 4))
       (v (copy-sequence v0)))
  (dotimes (i (length v))
    (aset v i (1+ (aref v i))))
  (list v0 v))
;; => ([1 2 3 4] [2 3 4 5])

หรือสร้างเวกเตอร์ใหม่ตั้งแต่เริ่มต้น

(let* ((v0 (vector 1 2 3 4))
       (v (make-vector (length v0) nil)))
  (dotimes (i (length v))
    (aset v i (1+ (aref v0 i))))
  (list v0 v))
;; => ([1 2 3 4] [2 3 4 5])
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.