首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何遍历列表并创建元素列表

如何遍历列表并创建元素列表
EN

Stack Overflow用户
提问于 2019-10-01 06:27:02
回答 2查看 246关注 0票数 0

我正在尝试转换clojure中的逻辑函数。我希望用户能够输入(convert '(and x y z)来产生(nor (nor x) (nor y) (nor z)。因此,我创建了一个带有第一个元素nor的列表,然后尝试创建在执行for循环时创建的其余元素列表。然而,for循环只是将所有列表组合在一起,并将nor保留在列表之外。我还想知道如何跳过列表中的第一个元素,但这不是我现在的首要任务。我对clojure比较陌生,不知道如何返回所有要放入更大列表中的列表。notor函数与该问题无关。

代码语言:javascript
复制
(defn lookup
  "Look up a value, i, in map m and returns the result if it exists. 
  Otherwise returns i."
  [i m]
  (get m i i))

(defn makelist
    [l]
    (for[i[l]] (list 'nor i)))

(defn convert
  [l]
  (let [p1 (first l)]
    (cond
      (= p1 'not) (map (fn [i] (lookup i '{not nor})) l)
      (= p1 'or) (list 'nor (map(fn [i] (lookup i '{or nor})) l))
      (= p1 'and) (list 'nor (makelist l))
      :else (print "error"))))

我得到的输出是(nor ((nor (and x y z))))。我想要的输出是(nor (nor and) (nor x) (nor y) (nor z)。我也不想要(nor and),但在我弄清楚如何跳过第一个元素之前,我只想把列表分开。

EN

回答 2

Stack Overflow用户

发布于 2019-10-01 09:03:44

我可以看到两个问题:

  1. makelist具有(for [i [l]] ...),因此它只生成一个项目,其中i绑定到整个传入列表l --这里您需要的是(for [i l] ...),以便处理l的每个元素,and
  2. convert's子句创建一个包含两个元素的列表:nor(makelist l)的结果--您需要的是(cons 'nor (makelist l)),这样您就可以获得一个列表,其中<i>d15是第一个元素,然后是调用makelist.

的结果的所有元素

我还没有检查convert的其他两个部分,看看您是否有类似的错误,但是通过上面的两个更改,(convert '(and x y z))将生成(nor (nor and) (nor x) (nor y) (nor z))

票数 2
EN

Stack Overflow用户

发布于 2019-10-01 21:31:50

只是为了好玩:我会在心理上扩展和概括你的任务,根据一些规则重写数据结构,这样你就可以声明(可能是递归的)重写规则,将任何输入转换为任何期望的输出。(并练习clojure)

让我们从简单的转换函数开始:

代码语言:javascript
复制
(defn convert [rules data]
  (if-let [res (some (fn [[condition rewrite]]
                       (when (condition data) (rewrite data)))
                     rules)]
    res
    data))

它找到适合您的输入的第一个规则(如果有),并应用它的转换函数:

代码语言:javascript
复制
(def my-rules [[sequential? (fn [data] (map #(convert my-rules %) data))]
               [number? inc]
               [keyword? (comp clojure.string/upper-case name)]])
#'user/my-rules

user> (convert my-rules [:hello :guys "i am" 30 [:congratulate :me]])
;;=> ("HELLO" "GUYS" "i am" 31 ("CONGRATULATE" "ME"))

使用这种方法,您的规则将如下所示:

代码语言:javascript
复制
(def rules
  [[(every-pred coll? (comp #{'not} first)) (fn [data] (map (partial convert [[#{'not} (constantly 'nor)]]) data))]
   [(every-pred coll? (comp #{'or} first)) (fn [data] (map (partial convert [[#{'or} (constantly 'nor)]]) data))]
   [(every-pred coll? (comp #{'and} first)) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])
#'user/rules

user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))

好吧,它可以工作,但看起来相当丑陋。尽管如此,我们仍然可以消除一些重复,为棋盘和转换器引入几个基本功能:

代码语言:javascript
复制
(defn first-is 
  "returns a function checking that the input is collection and it's head equals to value"
  [value]
  (every-pred coll? (comp #{value} first)))

将您的规则转换为:

代码语言:javascript
复制
(def rules
  [[(first-is 'not) (fn [data] (map (partial convert [[#{'not} (constantly 'nor)]]) data))]
   [(first-is 'or) (fn [data] (map (partial convert [[#{'or} (constantly 'nor)]]) data))]
   [(first-is 'and) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])
#'user/rules

user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))

然后介绍了替换重写规则:

代码语言:javascript
复制
(defn replacing
  ([new] [(constantly true) (constantly new)])
  ([old new] [#{old} (constantly new)])) 

引导我们

代码语言:javascript
复制
(def rules
  [[(first-is 'not) (fn [data] (map (partial convert [(replacing 'not 'nor)]) data))]
   [(first-is 'or) (fn [data] (map (partial convert [(replacing 'or 'nor)]) data))]
   [(first-is 'and) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])

现在我们可以看到,有一个函数的需求,转换集合中的每一项。让我们来介绍一下它:

代码语言:javascript
复制
(defn convert-each [rules]
  (fn [data] (map #(convert rules %) data)))

(def rules
  [[(first-is 'not) (convert-each [(replacing 'not 'nor)])]
   [(first-is 'or) (convert-each [(replacing 'or 'nor)])]
   [(first-is 'and) (fn [[_ & t]] (cons 'nor (map #(list 'nor %) t)))]])

user> (convert rules '(or x y z))
;;=> (nor x y z)

user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))

现在它好多了,但最后一个子句仍然有些难看。我可以考虑引入一个函数,它用单独的规则转换头部和尾部,然后协商转换后的头部和尾部:

代码语言:javascript
复制
(defn convert-cons [head-rules tail-conversion]
  (fn [[h & t]] (cons (convert head-rules h) (tail-conversion t))))

(defn transforming [transformer]
  [(constantly true) transformer])

(def rules
  [[(first-is 'not) (convert-each [(replacing 'not 'nor)])]
   [(first-is 'or) (convert-each [(replacing 'or 'nor)])]
   [(first-is 'and) (convert-cons [(replacing 'nor)]
                                  (convert-each [(transforming #(list 'nor %))]))]])

user> (convert rules '(and x y z))
;;=> (nor (nor x) (nor y) (nor z))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58176014

复制
相关文章

相似问题

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