【问题标题】:python/clojure equivalent to mathematica's NestWhileListpython/clojure 相当于mathematica的NestWhileList
【发布时间】:2011-03-13 23:14:22
【问题描述】:

动力:我正在在 python 中寻找可以得到我的东西

f([1,2,3]) == [[1,2,3], [2,3], [3]]

在 clojure 中,这只是(nest rest #(not (empty? %)) lst),或者如果我们有一个嵌套函数,它就是。我们要不要?我已经厌倦了盯着 clojure api 列表..

python 或 clojure 中的更好方法也将不胜感激..

【问题讨论】:

    标签: python clojure wolfram-mathematica


    【解决方案1】:
    data = [1,2,3]
    result = [ data[i:] for i in range(len(data)) ]
    

    【讨论】:

      【解决方案2】:

      返回序列:

      user> (take-while seq (iterate rest [1 2 3]))
      ([1 2 3] (2 3) (3))
      

      返回向量:

      user> (take-while seq (iterate #(subvec % 1) [1 2 3]))
      ([1 2 3] [2 3] [3])
      

      我已经看到这个模式被打包成一个 iterate-while 函数,它和你的 nest 函数几乎一样:

      (defn iterate-while [pred f x]
        (take-while pred (iterate f x)))
      

      请注意,(seq x) 等效于 (not (empty? x)),并且优先于 (not (empty? x))

      【讨论】:

        【解决方案3】:
        user> (reductions conj [] [1 2 3])
        ([] [1] [1 2] [1 2 3])
        

        也为您提供空版本。如果你愿意,你可以这样做

        user> (take-while identity (iterate next [1 2 3]))
        ([1 2 3] (2 3) (3))
        

        user> (rest (reductions conj [] [1 2 3]))
        ([1] [1 2] [1 2 3])
        

        【讨论】:

        • 你将如何让你的第一个和最后一个示例按照 OP 的要求执行?到目前为止,我没有发现比一小时前我的答案中的代码更好的(至少在眼睛上),您将其作为第二个示例。顺便说一句:我认为这样的东西至少会在 contrib 中,但没能找到它。也许我将它与 Haskell 的 tails 混淆了。
        • (map reverse (reverse (reductions conj [3] [2, 1]))) 产生 ((1 2 3) (2 3) (3))。要获得 OP 的 vec 结构,您需要 (vec (map #(vec (reverse %)) (reverse (reductions conj [3] [2, 1])))) 来产生 [[1 2 3] [ 2 3] [3]]
        • OP 没有说明顺序是否重要,所以我认为没有理由认为他认为我的任何建议都没用。我想他宁愿看到几种方法来做与他想要的事情相似的事情;如果他不关心订购它们,那么减少肯定是一个更短、更漂亮的解决方案。
        • 我不想说你的回答没用,但想知道,如果有可能以一种理智的方式使用reductions 获得正确的顺序(即不使用reverse两次)。如果我认为你的答案是无用的,我会投反对票。
        【解决方案4】:
        (partition-all 3 1 [1 2 3])
        

        产量

        ((1 2 3) (2 3) (3))
        

        如果你想要矢量格式

        (vec (map vec (partition-all 3 1 [1 2 3])))
        

        附言在 [1 2 3] 之前的 partition-all 中的 3 和 1 定义了向量应该以 3 个为一组进行分区,步长为 1,并且不是输入向量的一部分。我使用 partition-all 而不是 partition,因为 partition-all 不介意组短于指定长度 3。

        【讨论】:

        • 这很聪明,但在一般情况下,您必须将 3 替换为 (count lst)
        【解决方案5】:

        可能是这样的(我想到的第一件事,而且我最近没有做clojure,所以它可能不是最好的解决方案):

        (take-while identity (iterate next [1 2 3]))
        

        更新:

        贾斯汀建议的这个解决方案更可取(更短,[] 输入等):

        (take-whil­e seq (iter­ate rest ...))
        

        【讨论】:

        • 这可能是也可能不是问题,但(take-while identity (iterate next [])) 返回([])。对于这个用例,我希望它只返回一个空列表。使用 seq/rest 可以做到这一点。
        • 贾斯汀,使用seq/rest 似乎是更好的解决方案。相应地编辑了答案。谢谢指点!
        【解决方案6】:

        Python:

        def f(l):
            while l:
                yield l[:]
                l.pop(0)
        

        副本 ([:]) 取决于您是否需要该列表的副本,或者您可以就地修改它。如果您一次只需要其中一个子列表,则删除副本并迭代 f 可能会更快。

        另请注意,列表并不是最好的数据结构。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-17
          • 2016-01-19
          • 2011-04-18
          • 2020-04-15
          • 1970-01-01
          相关资源
          最近更新 更多