Sorting 在公共lisp中按两个属性排序
我需要在common lisp中按两个属性排序的帮助 假设我有一张清单: 1 x2 y1 x2 x3 y2 y我正在尝试按字符串和整数进行排序。 所以结果是1 x1 x2 x2 y2 y3 y 目前,我可以按变量或数字排序,但不能同时按变量和数字排序。如果输入2 x1 x1 y2 x1 y,则返回1 Y1 y2 x1 X2 X,而不是1 Y1 Y1 X2 X 我使用的代码是:Sorting 在公共lisp中按两个属性排序,sorting,lisp,common-lisp,Sorting,Lisp,Common Lisp,我需要在common lisp中按两个属性排序的帮助 假设我有一张清单: 1 x2 y1 x2 x3 y2 y我正在尝试按字符串和整数进行排序。 所以结果是1 x1 x2 x2 y2 y3 y 目前,我可以按变量或数字排序,但不能同时按变量和数字排序。如果输入2 x1 x1 y2 x1 y,则返回1 Y1 y2 x1 X2 X,而不是1 Y1 Y1 X2 X 我使用的代码是: (defun get-number (term) (destructuring-bind (number varia
(defun get-number (term)
(destructuring-bind (number variable) term
(declare (ignore variable))
number))
(defun get-variable (term)
(destructuring-bind (number variable) term
(declare (ignore number))
variable))
(defun varsort (p1)
(sort (copy-list p1) 'string> :key 'get-variable))
我的问题是,我如何才能按术语作为一个整体进行排序,使1 X而不仅仅是1或X。两个选项:
根据get编号对varsort的结果进行稳定排序
定义要在排序中使用的自定义比较函数:
是编写通用比较函数的好方法。由于您正在操作元组,因此可以更具体地编写以下内容:
(defun tuple-compare (comparison-functions)
(lambda (left right)
(loop for fn in comparison-functions
for x in left
for y in right
thereis (funcall fn x y)
until (funcall fn y x))))
例如:
(sort (copy-seq #((1 2) (2 3) (1 3) (2 1)))
(tuple-compare (list #'< #'<)))
=> #((1 2) (1 3) (2 1) (2 3))
两种选择:
根据get编号对varsort的结果进行稳定排序
定义要在排序中使用的自定义比较函数:
是编写通用比较函数的好方法。由于您正在操作元组,因此可以更具体地编写以下内容:
(defun tuple-compare (comparison-functions)
(lambda (left right)
(loop for fn in comparison-functions
for x in left
for y in right
thereis (funcall fn x y)
until (funcall fn y x))))
例如:
(sort (copy-seq #((1 2) (2 3) (1 3) (2 1)))
(tuple-compare (list #'< #'<)))
=> #((1 2) (1 3) (2 1) (2 3))
可以通过组合谓词来实现这一点。如果您有一个可以比较变量的谓词和一个可以比较系数的谓词,那么您可以轻松地创建一个新的谓词来检查一个谓词,如果第一个谓词提供了一个确定的答案,则返回一个确定的答案,如果第二个谓词没有提供答案,则遵从第二个谓词。这也可用于其他应用程序:
(defun and-then (original-predicate next-predicate)
"Returns a new predicate constructed from ORIGINAL-PREDICATE and
NEXT-PREDICATE. The new predicate compares two elements, x and y, by
checking first with ORIGINAL-PREDICATE. If x is less than y under
ORIGINAL-PREDICATE, then the new predicate returns true. If y is less
than x under ORIGINAL-PREDICATE, then the new predicate returns false.
Otherwise, the new predicate compares x and y using NEXT-PREDICATE."
(lambda (x y)
(cond
((funcall original-predicate x y) t)
((funcall original-predicate y x) nil)
(t (funcall next-predicate x y)))))
然后很容易调用,然后“variable<”coefficient,您可以通过组合谓词来实现这一点。如果您有一个可以比较变量的谓词和一个可以比较系数的谓词,那么您可以轻松地创建一个新的谓词来检查一个谓词,如果第一个谓词提供了一个确定的答案,则返回一个确定的答案,如果第二个谓词没有提供答案,则遵从第二个谓词。这也可用于其他应用程序:
(defun and-then (original-predicate next-predicate)
"Returns a new predicate constructed from ORIGINAL-PREDICATE and
NEXT-PREDICATE. The new predicate compares two elements, x and y, by
checking first with ORIGINAL-PREDICATE. If x is less than y under
ORIGINAL-PREDICATE, then the new predicate returns true. If y is less
than x under ORIGINAL-PREDICATE, then the new predicate returns false.
Otherwise, the new predicate compares x and y using NEXT-PREDICATE."
(lambda (x y)
(cond
((funcall original-predicate x y) t)
((funcall original-predicate y x) nil)
(t (funcall next-predicate x y)))))
然后很容易调用,然后调用“variable<”coefficient当你说另一个键时,你是指get number吗?当你说另一个键时,你是指get number吗?堆栈溢出的贡献是根据允许复制和复制的条款许可的。复制和重用东西是可以的,但属性是必需的。虽然您已经更改了函数的实际名称,但似乎您的访问器get number和get variable以及varsort的主体都是从中复制的。可以这样复制它们,但您可能应该在这里包含一个指向您前面问题的链接。对堆栈溢出的贡献是根据允许复制和复制的条款授权的。复制和重用东西是可以的,但属性是必需的。虽然您已经更改了函数的实际名称,但似乎您的访问器get number和get variable以及varsort的主体都是从中复制的。可以这样复制它们,但是您可能应该在这里包含一个指向您先前问题的链接。谢谢!我在Emacs中使用ace窗口来切换窗口,但我希望窗口按框架顶部、左侧和在一个框架内编号,就像你在书中读到的那样,从顶部开始,从左到右编号,然后向下编号,从左到右编号,等等。然后与你的和进行比较,我添加了defun make composited comparators l seq减少lambda old new,然后通过“
(defun term-coefficient (term)
(first term))
(defun coefficient< (term1 term2)
(< (term-coefficient term1)
(term-coefficient term2)))
(defun term-variable (term)
(second term))
(defun variable< (term1 term2)
(string< (term-variable term1)
(term-variable term2)))
(defparameter *sample*
'((1 x)(2 y)(1 x)(2 x)(3 y)(2 y)))
CL-USER> (sort (copy-list *sample*) 'coefficient<)
((1 X) (1 X) (2 Y) (2 X) (2 Y) (3 Y))
CL-USER> (sort (copy-list *sample*) 'variable<)
((1 X) (1 X) (2 X) (2 Y) (3 Y) (2 Y))
CL-USER> (sort (copy-list *sample*) (and-then 'variable< 'coefficient<))
((1 X) (1 X) (2 X) (2 Y) (2 Y) (3 Y))
(defun compare-by (predicate key)
"Returns a function that uses PREDICATE to compare values extracted
by KEY from the objects to compare."
(lambda (x y)
(funcall predicate
(funcall key x)
(funcall key y))))
(defun coefficient< (term1 term2)
(funcall (compare-by '< 'term-coefficient) term1 term2))
(defun variable< (term1 term2)
(funcall (compare-by 'string< 'term-variable) term1 term2))
(defun varsort (p1)
(sort (copy-list p1)
(and-then (compare-by '< 'term-coefficient)
(compare-by 'string< 'term-variable))))