2013-08-12 2 views
1

Кажется, что equal не может правильно сравнить таблицу хэшей. Вот exmapleсравнить хеш-таблицу в emacs lisp?

(defun hash-alist (alist) 
    "Convert association list to a hash table and return it." 
    (let ((my-hash (make-hash-table :test 'equal))) 
    (dolist (entry alist) 
     (puthash (car entry) (cdr entry) my-hash)) 
    my-hash)) 
(setq a '((?a . 1) (?b . 2))) 
(setq b (hash-alist a)) 
(setq c (hash-alist a)) 
(equal b c) 

Последняя строка кода возвращает nil. Есть ли другая функция для сравнения двух хеш-таблиц?

+0

Я не знаю ни одного стандарта. Вы можете найти/реализовать некоторую библиотеку, которая выполняет задание «минус». Тогда хэши равны, если результат множества минус имеет длину 0. –

ответ

2

, так как нет функции builtin Emacs для этого. Я написал это только в случае, если люди будут заинтересованы:

(defun hash-equal (hash1 hash2) 
    "Compare two hash tables to see whether they are equal." 
    (and (= (hash-table-count hash1) 
      (hash-table-count hash2)) 
     (catch 'flag (maphash (lambda (x y) 
           (or (equal (gethash x hash2) y) 
            (throw 'flag nil))) 
          hash1) 
       (throw 'flag t)))) 
+0

Довольно многое, о чем я думал :) – phils

0

Я предполагаю, что с комбинацией функций hash-table-count, maphash и gethash вы можете легко выполнить собственный тест равенства хэш-таблицы.

1

С 2013 существует современная библиотека хеш-таблицы для Emacs: ht. Он предоставляет многофункциональный API, аналогичный dash для списков и деревьев, s для строк, f для файлов.

Установка библиотек сторонних в Emacs 24 очень просто, читайте htinstallation instructions.

Нет встроенной функции равенства в ht, поэтому нам еще нужно написать собственную функцию. Есть два способа, я думаю, из тестирования 2 хэш-таблиц для равенства:

(defun ht-equal-1 (t1 t2) 
    (equal (ht-items t1) (ht-items t2))) 

(defun ht-equal-2 (t1 t2) 
    (and (= (ht-size t1) 
      (ht-size t2)) 
     (ht-map (lambda (k v) (equal (ht-get t1 k) v)) 
       t2))) 

Они оба должны быть быстро для небольших хэш-таблиц, но мы не уверены, какой из них быстрее для больших хэш-таблиц, поэтому давайте создадим относительно большой хеш-таблицу с помощью ht<-plist:

(setq foo-table-1 (ht<-plist (number-sequence 1 10000) 'equal)) 
(setq foo-table-2 (ht<-plist (number-sequence 1 10000) 'equal)) 

Существует большая функция Elisp benchmark-run, которая может запустить функцию или выражение Elisp несколько раз, а затем сообщить время, которое потребовалось. Давайте запустим наши 2 функции, каждая из сравнения 2 хэш-таблицы, мы только что создали:

(benchmark-run 1000 (ht-equal-1 foo-table-1 foo-table-2)) 
;; => (5.36585361 4 0.6110091979999996) 
(benchmark-run 1000 (ht-equal-2 foo-table-1 foo-table-2)) 
;; => (3.708278817 0 0.0) 

кажется ht-equal-2 работает быстрее, так что вы должны использовать.