mFontoura
mFontoura

Reputation: 257

Sorting chapters numbers, like 1.2.1 or 1.4.2.4

I have the Model Chapter:

class Chapter(ndb.Model):
    tutKey = ndb.KeyProperty(kind='Tutorial')
    title = ndb.StringProperty(required=True)
    content = ndb.TextProperty(required=True)
    note = ndb.TextProperty()
    lvl = ndb.IntegerProperty(default=0)
    order = ndb.IntegerProperty(default=0)
    parentID = ndb.KeyProperty(kind='Chapter')
    number = ndb.IntegerProperty()

'number' is the base chapter (chap1 or chap 1.2 have number = 1). 'lvl' is for the depth of the chapter, for example, in chap1.1.1 the lvl is 3 and in chap1.1.1.1 lvl is 4. And the 'order' says the order of the chap, for example, in chap1.2 'order' is 2 and in chap2.2 'order' is also 2.

How can i sort the following chapters (for example)?

chapter 2
chapter 2.1
chapter 1.1.1
chapter 1.1
chapter 1

I have been thinking... should i create a StringProperty to save the chapter number like "1.2.1" and then split the string by '.' ?


EDIT: i created a ndb.IntegerProperty(repeated=True) the equivalent to ListProperty suggested by JBernardo. I'm able to store the data correctly, but I can't get a way to sort by the property. Anyone knows how to do this?

Upvotes: 0

Views: 437

Answers (3)

mFontoura
mFontoura

Reputation: 257

Found a simpler way to solve my problem. I store the chapter in a different way. In ndb.IntegerProperty(repeated=True). This way i can sort it just my using:

newChaps = sorted(chaps, key=lambda obj: obj.version)

Where 'version' is the ndb.IntegerProperty.

Done.

Upvotes: 0

user784435
user784435

Reputation:

The first thing that sprung into my mind was to set up your routes to handle the chapters so to have something like:

1/1
1/2/1

etc

Upvotes: 0

Holger
Holger

Reputation: 2195

You can represent your chapters by tuples with the length of the maximum depths of sub-chapters. Not used sub-chapters are represented by zeros. Then following would be a representation of your chapters:

chapter 2      (2, 0, 0)
chapter 2.1    (2, 1, 0)
chapter 1.1.1  (1, 1, 1)
chapter 1.1    (1, 1, 0)
chapter 1      (1, 0, 0)

If these chapters are added to a list l, this list can be sorted by the lists' sort method.

chapters = [(2, 0, 0), (2, 1, 0), (1, 1, 1), (1, 1, 0), (1, 0, 0)]
chapters.sort()
print chapters

This gives:

[(1, 0, 0), (1, 1, 0), (1, 1, 1), (2, 0, 0), (2, 1, 0)]

--- EDIT ---

In case of dynamic comparison you can add a function to the sort method via the key option. This function is applied to every element of the list before sorting. In the following expandChapter expands a chapter ch to the depth depth. The key argument in sort accepts only one parameter. Therefore, the maximum depth maxdepth is calculated and expandChapters is given to sort via anonymous lambda function.

def expandChapter(ch, depth):
    ch = ch + (0,) * (depth - len(ch))
    return ch

print expandChapter((1,), 3)                                # prints (1, 0, 0)

chapters = [(2,), (2, 1,), (1, 1, 1,), (1, 1), (1,)]
maxdepth = max([len(i) for i in chapters])
print maxdepth                                              # prints 3

chapters.sort(key = lambda x: expandChapter(x, maxdepth))
print chapters

This gives the correct answer:

[(1,), (1, 1), (1, 1, 1), (2,), (2, 1)]

Upvotes: 3

Related Questions