3

Impetus: I was looking for something in python which would get me

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

In clojure, this would just be (nest rest #(not (empty? %)) lst), or it would if we had a nest function. Do we? I'm tired of staring at the clojure api list..

Better approaches in python or clojure would also be appreciated..

Ellery Newcomer
  • 1,594
  • 1
  • 11
  • 23

6 Answers6

3
data = [1,2,3]
result = [ data[i:] for i in range(len(data)) ]
FMc
  • 41,963
  • 13
  • 79
  • 132
3

Return seqs:

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

Return vectors:

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

I've seen this pattern packaged up into an iterate-while function, which is pretty much the same as your nest function:

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

Note that (seq x) is equivalent to, and preferred over, (not (empty? x))

Justin Kramer
  • 3,983
  • 1
  • 23
  • 23
1

Maybe something like this (the first thing that came to my mind, and I haven't been doing clojure recently, so it might not be the best solution):

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

Update:

This solution Justin suggested is preferable (shorter, [] input, etc.):

(take-whil­e seq (iter­ate rest ...))
danlei
  • 14,121
  • 5
  • 58
  • 82
  • This may or may not be an issue, but `(take-while identity (iterate next []))` returns `([])`. For this use case I would expect it to return just an empty list. Using seq/rest does that. – Justin Kramer Mar 14 '11 at 23:14
  • Justin, using `seq`/`rest` seems to be the better solution. Edited the answer accordingly. Thanks for the pointer! – danlei Mar 15 '11 at 01:02
1
user> (reductions conj [] [1 2 3])
([] [1] [1 2] [1 2 3])

Gets you the empty version as well. If you want, you can instead do

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

or

user> (rest (reductions conj [] [1 2 3]))
([1] [1 2] [1 2 3])
amalloy
  • 89,153
  • 8
  • 140
  • 205
  • And how would you make your first and last examples do what the OP asked for? So far, I found nothing better (at least to the eye) than the code from my answer an hour ago, which you included as your second example. Btw: I thought that somethig like that would at least be in contrib, but didn't manage to find it. Maybe I'm confusig it with Haskell's `tails` though. – danlei Mar 14 '11 at 02:13
  • (map reverse (reverse (reductions conj [3] [2, 1]))) yields ((1 2 3) (2 3) (3)). To get the vec structure of the OP, you would need (vec (map #(vec (reverse %)) (reverse (reductions conj [3] [2, 1])))) to yield [[1 2 3] [2 3] [3]] – bOR_ Mar 14 '11 at 08:55
  • OP didn't specify whether order matters, so I see no reason to suppose that he finds any of my suggestions useless. I imagine he'd rather see several ways of doing something similar to what he wants; if he doesn't care about order them reductions is certainly a shorter, prettier solution. – amalloy Mar 14 '11 at 08:56
  • I didn't want to say that your answer is useless, but wanted to know, if it is possible to get the right order with `reductions` in a sane way (i.e. without using `reverse`two times). If I thought your answer were useles, I would have downvoted. – danlei Mar 14 '11 at 18:06
1
(partition-all 3 1 [1 2 3])

yields

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

if you want it in a vector format

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

p.s. the 3 and the 1 in partition-all prior to the [1 2 3] define that the vector should be partitioned in groups of 3, with a stepsize of 1, and are not part of the input vector. I use partition-all instead of partition, because partition-all doesn't mind about groups being shorter than the specified length of 3.

bOR_
  • 381
  • 1
  • 3
0

Python:

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

The copy ([:]) depends on whether you want a copy of the list or you are OK with modifying it in place. If you only need one of the sublists at a time, it may be faster to remove the copy and iterate over f.

Note also that a list is not the best data structure for this.

Katriel
  • 120,462
  • 19
  • 136
  • 170