1

I have a nested list that is similar to this and sorted on time ascending:

[[TIME, 'b', 0],
[TIME, 'b', 1],
[TIME, 'b', 1],
[TIME, 'b', 1],
[TIME, 'b', 10],
[TIME, 'b', 0],
[TIME, 'b', 1],
[TIME, 'b', 1],
[TIME, 'b', 10],
[TIME, 'b', 0],
[TIME, 'b', 1],
[TIME, 'b', 1],
[TIME, 'b', 1],
[TIME, 'b', 1],
[TIME, 'b', 10]]

The third item in each list is either a 0, 1 or 10. 0 represents the start, 1 represents moving and 10 represents the finish. How can I split this into a further nested list so I would end up with a list of journeys similar to this:

[[[TIME, 'b', 0],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 10]],
[[TIME, 'b', 0],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 10]],
[[TIME, 'b', 0],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 10]]]
7wonders
  • 1,639
  • 1
  • 17
  • 34
  • Ive been trying to get my head around these but have not been successful: http://stackoverflow.com/questions/5936771/python-how-to-split-a-list-into-an-unknown-number-of-smaller-lists-based-on-a-d http://stackoverflow.com/questions/949098/python-split-a-list-based-on-a-condition – 7wonders Aug 26 '12 at 23:47
  • That first link is a good one, and has several viable solutions. Maybe the simplest nontrivial one to start with is the list comprehension one: make a list of the indices which have elements with the last term equal to zero, and then make a new list slicing from each index to the next. – DSM Aug 26 '12 at 23:54
  • You can just iterate over the list and add the elements to the sublist until you encounter an item with `10` (like shown in the first of your links). – Felix Kling Aug 26 '12 at 23:55
  • I would suggest that you pay attention to the answer by [Cedric Julien](http://stackoverflow.com/a/5936831/577088). The other answers have merits, but they aren't as simple and clear. – senderle Aug 26 '12 at 23:57

5 Answers5

4

Probably there's a more pythonic way to do this, but this is functional, straight forward and should be easy to follow. biglist holds the initial data.

newlist = []
sublist = []
for i in biglist:
    sublist.append(i)
    if i[2] == 10:
        newlist.append(sublist)
        sublist = []

gives:

[[[TIME, 'b', 0],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 10]],
[[TIME, 'b', 0],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 10]],
[[TIME, 'b', 0],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 1],[TIME, 'b', 10]]]
Levon
  • 138,105
  • 33
  • 200
  • 191
  • 1
    Well, this was one of the first answers so it was the first I tried and it works perfectly. – 7wonders Aug 27 '12 at 00:06
  • It does seem to add an extra set of opening and closing [] though around the main list – 7wonders Aug 27 '12 at 00:15
  • 1
    Upvoted because there's a lot to be said for straightforwardness. Even a non-Python programmer can look at that and figure out what's happening. More importantly, you'll be able to figure it out yourself when you come back next year to maintain it. – Kirk Strauser Aug 27 '12 at 00:15
  • for some reason I seem to get an extra [ at the beginning and ] at the end so instead of just three its four – 7wonders Aug 27 '12 at 00:19
  • @Levon: I can reproduce the extra nesting from this code, FWIW. – DSM Aug 27 '12 at 00:22
  • 1
    But I fully agree with Kirk, I can actually read this, understand whats happening and learn from it. thikonom's answer below works perfectly too and if I could share my accept with him I would. – 7wonders Aug 27 '12 at 00:22
  • @DSM Never mind ... my problem was related to *how* I was printing out the result for verification .. "facepalm" – Levon Aug 27 '12 at 00:30
1
#x is your initial list
k, new_list = 0, []
for i,j in enumerate(x):
    if j[2] == 10:
        new_list.append(x[k:i+1])
        k = i+1
thikonom
  • 4,219
  • 3
  • 26
  • 30
1

Contrary to the other solution, here we test on whether the journey begins (d[2] == 0) instead of when it ends:

output = []
for d in data:
    if d[2] == 0:
        # Starting a new journey: we add a new list
        output.append([d])
    else:
        # Continuing a journey: we extend the last list
        output[-1].extend([d])

Of course, this gonna fail if the first journey never starts (you'll get an IndexError from the else statement)...

Pierre GM
  • 19,809
  • 3
  • 56
  • 67
0

The most obvious solution, if I have understood the question properly:

def iter_journeys(lst):
    for e in lst:
        act = e[2]

        if act == 0:
            journey = []

        journey.append(e)

        if act == 10:
            yield journey
Eldar Abusalimov
  • 24,387
  • 4
  • 67
  • 71
0

I'm sure there's a more efficient way of doing this, but here's a basic solution:

def create_journeys(paths):
  journeys = [[]]

  for path in paths:
    journeys[-1].append(path)

    if path[-1] == 10:
      journeys.append([])

  return journeys
Blender
  • 289,723
  • 53
  • 439
  • 496