unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: Xah <xahlee@gmail.com>
To: help-gnu-emacs@gnu.org
Subject: Re: elisp optimization question
Date: Thu, 8 May 2008 17:36:18 -0700 (PDT)	[thread overview]
Message-ID: <c7c13a5d-462e-474f-b022-b1764ccd329b@1g2000prg.googlegroups.com> (raw)
In-Reply-To: mailman.11345.1210283700.18990.help-gnu-emacs@gnu.org

On May 8, 11:03 am, brad clawsie <claw...@fastmail.fm> wrote:
> hi, i use the following function to translate unicode and other
> entities found on the web into ascii that i can view in emacs-w3m. i
> am concerned that each search and replace as done in my example is
> inefficient, is there a better way to do this? i.e., is there a better
> way to group search/replace pairs? thanks in advance!
>
> (defun w3m-filter-brad (url)
>   (goto-char (point-min))
>   (while (re-search-forward "&#187;" nil t)
>     (replace-match "&gt;&gt;"))
>   (goto-char (point-min))
>   (while (re-search-forward "&#8217;" nil t)
>     (replace-match "'"))
...
>   )

I had similar problem and also thought about the efficiency or
different implementation issues.

Here's a alternative implementation. The idea is that instead of
working on buffer, you grab them into a string, and do replacement on
the string, then put them back in buffer. I haven't tested whether it
is faster, but i think David Kastrup mentioned in the past that
working on string is slower.

(defun fold (f x li)
  "Recursively apply (f x i), where i is the ith element in the list
li.\n
For example, (fold f x '(1 2)) returns (f (f x 1) 2)"
  (let ((li2 li) (ele) (x2 x))
    (while (setq ele (pop li2))
      (setq x2 (funcall f x2 ele))
    )
    x2
  )
)

(defun replace-string-pairs (str pairs)
"Replace the string str repeatedy by the list pairs.\n
Example: (replace-string-pairs \"yes or no\"
'( (\"yes\" \"no\") (\"no\" \"n\") ) )
 ⇒  \"n or n\""
(fold (lambda (x y) ""
        (replace-regexp-in-string
         (nth 0 y) (nth 1 y) x) ) str pairs) )

you might use replace-string instead of replace-regexp-in-string.

--------------------

Also, the following are 3 different implementations.

The first is same as yours except in works on region, by first narrow-
to-region. The second is avoided the narrow-to-region by grabing the
region as string and work on the string. Since i heard that working on
string is slower, and since i want to avoid narrow-to-region, i
thougth of using a temp buffer instead. That's the third solution,
which i believe to be the best.

However, at the time either the 2nd or the 3rd solution had a bug, so
i switched back to the first. I haven't had time to investigate what
was the problem.


(defun replace-string-pairs-region (start end mylist)
  "Replace string pairs in region.
Example syntax:
 (replace-string-pairs-region start end '((\"alpha\" \"α\") (\"beta\"
\"β\")))
The search string and replace string are all literal."
  (save-restriction
    (narrow-to-region start end)
    (mapc
      (lambda (arg)
        (goto-char (point-min))
        (while (search-forward (car arg) nil t) (replace-match (cadr
arg) t t) ))
      mylist)))

(defun replace-string-pairs-region2 (start end mylist)
  "Replace string pairs in region.
Same as replace-string-pairs-region but with different implementation.
This implementation does not use narrow-to-region or save-restriction.
Is cleaner in a sense."
  (let (mystr)
    (setq mystr (buffer-substring start end))
    (mapc
     (lambda (x) (setq mystr (replace-regexp-in-string (car x) (cadr
x) mystr)))
     mylist)
    (delete-region start end)
    (insert mystr)
    )
)

(defun replace-string-pairs-region3 (start end mylist)
  "Replace string pairs in region.
Same as replace-string-pairs-region but with different
implementation."
  (let (mystr tempbuff)
    (setq mystr (buffer-substring start end))
    (setq tempbuff (concat " " (random)))
    (save-current-buffer
      (set-buffer (get-buffer-create tempbuff))
      (insert mystr)
      (mapc
       (lambda (arg)
         (goto-char (point-min))
         (while (search-forward (car arg) nil t) (replace-match (cadr
arg) t t) ))
       mylist)
      (kill-buffer tempbuff)
      )
    (delete-region start end)
    (insert mystr)
    )
  )

  Xah
  xah@xahlee.org
∑ http://xahlee.org/

  parent reply	other threads:[~2008-05-09  0:36 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <mailman.11345.1210283700.18990.help-gnu-emacs@gnu.org>
2008-05-09  0:00 ` elisp optimization question harven
2008-05-09  1:45   ` Kevin Rodgers
     [not found]   ` <mailman.11354.1210297808.18990.help-gnu-emacs@gnu.org>
2008-05-09  9:59     ` Rupert Swarbrick
2008-05-09 21:43       ` harven
2008-05-09  0:36 ` Xah [this message]
2008-05-08 18:03 brad clawsie
2008-05-08 22:14 ` Lennart Borgman (gmail)
2008-05-09  1:42   ` Kevin Rodgers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c7c13a5d-462e-474f-b022-b1764ccd329b@1g2000prg.googlegroups.com \
    --to=xahlee@gmail.com \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).