首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在通用Lisp中,字符串和数字之间的核心区别是什么?

在通用Lisp中,字符串和数字之间的核心区别是什么?
EN

Stack Overflow用户
提问于 2013-08-13 09:14:28
回答 3查看 202关注 0票数 2

作为CL的新手,我经常使用简单的算法。例如,我试图实现一个函数,用于删除列表中的所有唯一元素。

(1 2 2 3 3 4 5 3) -> (2 2 3 3 3)

第一次尝试导致以下代码:

代码语言:javascript
复制
(defun remove-unique (items)
  (let ((duplicates (set-difference items (remove-duplicates items :test #'equal))))
    (append duplicates (remove-duplicates duplicates :test #'equal))))

这在字符串中工作正常,但总是返回数字的NIL。阅读更多关于set-difference的内容,我了解到它根本不适合使用重复填充的列表,在我的例子中它只是起作用,所以我放弃了不可移植的方法,继续前进。

另一种尝试是:

代码语言:javascript
复制
(defun remove-unique (items)
  (loop for item in items 
    when (member item (cdr (member item items)))
    collect item))

这对于数字来说是可行的,但是返回字符串的NIL

显然,在字符串和数字之间有一个核心的区别,我不明白。为什么列表处理函数(如memberset-difference )对它们的工作方式不同?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-08-13 22:10:15

字符串与列表比数字更相关,因为列表和字符串都是序列。

"Hello"是一个序列(复合数据类型),从原始字符值#\H开始,以#\o结尾。

'(1 2 3)是以基元数值1开头,以3结尾的序列(复合数据类型)。

字符与数字相似,因为它们是原始值。原语值可以使用eql进行比较,而不属于同一对象的序列可以使用equal进行比较。

代码语言:javascript
复制
(setq list1 (list 1 2 3))
(setq list2 (list 1 2 3))

(eql list1 list2) 
;==> NIL

(equal list1 list2)
;==> T

;; comparing first element of both lists using eql
(eql (car list1) (car list2))
;==> T

(setq string1 "Hello")
(setq string2 "Hello")

(eql string1 string2)
;==> NIL

(equal string1 string2)
;==> T

;; comparing first character of both strings using eql
(eql (elt string1 0) (elt string2 0))
;==> T

公共Lisp中的大多数函数(如果不是全部的话)通常都有一个可选的名为:test的参数,您可以在这里提供元素比较的方式。默认情况下通常是eql。为了使它们与序列相一致,您需要将#'equal作为:test提供。

票数 1
EN

Stack Overflow用户

发布于 2013-08-14 06:49:15

数字、字符和字符串的相等比较确实不同。Equal,您应该小心使用它,因为它更昂贵,结构相等(因此它下降到某些对象)。eq做对象相等。除了数字(检查类型和值)和字符(检查“值”)外,大多数情况下eql都是对象相等的。

有关更多信息,请参见相等eql情商的hyperspec条目。

票数 2
EN

Stack Overflow用户

发布于 2013-08-13 09:52:41

代码语言:javascript
复制
(defun remove-unique (items &key (test 'eql))
  (loop
     :with table := (make-hash-table :test test)
     :for element :in items :do
     (setf (gethash element table)
           (1+ (gethash element table 0)))
     :finally
     (return
       (loop
          :for k :being :the :hash-keys :of table
          :using (:hash-value v)
          :when (> v 1) :nconc (make-list v :initial-element k)))))

(defun remove-unique (items &key (test 'eql))
  (loop
     :with table := (make-hash-table :test test)
     :for element :in items :do
     (setf (gethash element table)
           (1+ (gethash element table 0)))
     :finally
     (return
       (loop
          :for element :in items
          :unless (= 1 (gethash element table))
          :collect element))))

我可能会使用第一个变体,因为它减少了对哈希表的读取,但是您需要检查列表中的项以后没有修改。

代码语言:javascript
复制
(remove-unique '("1" "2" "2" "3" "3" "4" "5" "3") :test #'equal)

给予:

代码语言:javascript
复制
("2" "2" "3" "3" "3")

代码语言:javascript
复制
(remove-unique '("1" "2" "2" "3" "3" "4" "5" "3"))

给予:

代码语言:javascript
复制
NIL
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18205073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档