2013-06-26 18 views
12

Tôi đang tìm kiếm một số tương đương replace-regexp-in-string chỉ sử dụng chuỗi ký tự, không có cụm từ thông dụng.Tìm kiếm một hàm thay thế trong chuỗi trong elisp

(replace-regexp-in-string "." "bar" "foo.buzz") => "barbarbarbarbarbarbarbar" 

Nhưng tôi muốn

(replace-in-string "." "bar" "foo.buzz") => "foobarbuzz" 

tôi đã cố gắng nhiều replace-* chức năng nhưng không thể tìm nó ra.

Sửa

Đổi lại cho câu trả lời phức tạp tôi quyết định điểm chuẩn cho họ (yea, tôi biết tất cả các tiêu chuẩn là sai, nhưng nó vẫn còn thú vị).

Kết quả của benchmark-run(time, # garbage collections, GC time):

(benchmark-run 10000 
    (replace-regexp-in-string "." "bar" "foo.buzz")) 

    => (0.5530160000000001 7 0.4121459999999999) 

(benchmark-run 10000 
    (haxe-replace-string "." "bar" "foo.buzz")) 

    => (5.301392 68 3.851943000000009) 

(benchmark-run 10000 
    (replace-string-in-string "." "bar" "foo.buzz")) 

    => (1.429293 5 0.29774799999999857) 

replace-regexp-in-string với một chiến thắng regexp trích dẫn. Bộ đệm tạm thời hoạt động tốt.

Chỉnh sửa 2

Bây giờ với biên soạn! Phải làm 10x nhiều lần lặp:

(benchmark-run 100000 
    (haxe-replace-string "." "bar" "foo.buzz")) 

    => (0.8736970000000001 14 0.47306700000000035) 

(benchmark-run 100000 
    (replace-in-string "." "bar" "foo.buzz")) 

    => (1.25983 29 0.9721819999999983) 

(benchmark-run 100000 
    (replace-string-in-string "." "bar" "foo.buzz")) 

    => (11.877136 86 3.1208540000000013) 

haXe-thay-chuỗi được tìm kiếm tốt

+1

Thời gian cho 'haxe-replace-string' có thể quá tệ vì bạn không biên dịch byte? 'loop' macro thực sự làm biên dịch phải, nó rất chậm nếu không. –

+0

được cập nhật với một số số khác – spike

+1

(thay thế-regexp-in-string "\\." "Bar" "foo.buzz") => "foobarbuzz" – vitaly

Trả lời

14

Hãy thử điều này:

(defun replace-in-string (what with in) 
    (replace-regexp-in-string (regexp-quote what) with in nil 'literal)) 
+3

Dấu ngoặc đơn thứ hai để cuối cùng phải được di chuyển ra ngoài, nhưng nếu không thì tác vụ này . Không có nội trang cho điều này? Có vẻ như một thứ kỳ lạ như vậy bị bỏ lại. – spike

+0

@spike Tôi đọc ở đâu đó mà cách được gợi ý là tạo một bộ đệm tạm thời, sao chép chuỗi đó và 'thay thế chuỗi' trên bộ đệm. Sẽ rất thú vị nếu như vậy nó nhanh hơn. –

+1

@spike - cố định. –

3

Tôi không muốn hy vọng cho điều này là nhanh hơn:

(defun haxe-replace-string (string string-a string-b) 
    "Because there's no function in eLisp to do this." 
    (loop for i from 0 upto 
     (- (length string) (length string-a)) 
     for c = (aref string i) 
     with alen = (length string-a) 
     with result = nil 
     with last = 0 
     do (loop for j from i below (+ i alen) 
       do (unless 
         (char-equal 
         (aref string-a (- j i)) 
         (aref string j)) 
         (return)) 
       finally 
       (setq result 
         (cons (substring string last (- j alen)) result) 
         i (1- j) last j)) 
     finally 
     (return 
     (if result 
      (mapconcat 
       #'identity 
       (reverse (cons (substring string last) result)) string-b) 
      string)))) 

Becasue replace-regexp-in-string là một chức năng gốc, nhưng bạn không bao giờ biết ... Dù sao, tôi đã viết điều này một thời gian trước đây cho một số lý do, vì vậy, nếu bạn điền vào như so sánh hiệu suất - bạn được chào đón để thử :)

ý tưởng khác, sử dụng bộ đệm tạm thời:

(defun replace-string-in-string (what with in) 
    (with-temp-buffer 
    (insert in) 
    (beginning-of-buffer) 
    (while (search-forward what nil t) 
     (replace-match with nil t)) 
    (buffer-string))) 
8

s.el thư viện chuỗi thao tác có s-replace chức năng:

(s-replace "." "bar" "foo.buzz") ;; => "foobarbuzz" 

Tôi khuyên bạn nên cài đặt s.el từ trình quản lý gói Emacs, nếu bạn làm việc với các chuỗi trong Elisp của bạn.