View Single Post
Old 04-13-2023, 03:25 PM   #574
isarl
Addict
isarl ought to be getting tired of karma fortunes by now.isarl ought to be getting tired of karma fortunes by now.isarl ought to be getting tired of karma fortunes by now.isarl ought to be getting tired of karma fortunes by now.isarl ought to be getting tired of karma fortunes by now.isarl ought to be getting tired of karma fortunes by now.isarl ought to be getting tired of karma fortunes by now.isarl ought to be getting tired of karma fortunes by now.isarl ought to be getting tired of karma fortunes by now.isarl ought to be getting tired of karma fortunes by now.isarl ought to be getting tired of karma fortunes by now.
 
Posts: 287
Karma: 2534928
Join Date: Nov 2022
Location: Canada
Device: Kobo Aura 2
Quote:
Originally Posted by Levinas2021 View Post
Hello everyone,

I'm using Calibre Portable to manage my ebooks and I have a column named Ranking with a numeric value for each book.
I would like to create a new column called Ranking Position that displays the position of each book based on their value in the Ranking column (book with highest value has position number 1).
I'm not very familiar with Calibre's functions, so I was wondering if anyone could help me with the steps to populate this new column automatically.

Thank you in advance!


I don't believe Calibre's built-in functions have a useful way of ranking values, but Python does, if you're willing to bust out the big guns. Here is an example which I think will do approximately what you are after. I am assuming that your “ranking” is better the higher it is. If I've made the wrong assumption here, and a lower “ranking” value means a better-ranked book, then simply change reverse=True to reverse=False. The title:true argument is merely meant to represent a search query which will return all books. The ampersand may be replaced with any arbitrary value that will never appear within the values you are looking up; make sure to replace it in both places on that first (3rd) line of code. Finally, if you wish to restrict your search to the current virtual library, replace that 0 with a 1. Finally, this code will assign the top rank a value of 1 – without the “1 +” on the last line, the top-ranked book would have a rank of 0.

Code:
python:
def evaluate(book, context):
	vals = context.funcs.book_values('#ranking', 'title:true', '&', 0).split('&')
	vals = sorted([float(v) for v in vals], reverse=True)
	return str(1 + vals.index(float(book.get('#ranking'))))
Warning: if you have multiple books with an identical ranking, the above code will NOT correctly count ties. For example, if your top rank is shared by two books, the next rank will be 2, not 3. If you wish to fix this error then you will have to modify the code; the error arises because the book_values() function returns unique values. In order to have it count correctly in the case of ties, you will need to count the multiplicity of each value in your library, and add that many copies of the value to the vals list. I'm ignoring this because it seems like your ranking value has enough precision to easily avoid duplicates, but that assumption may be incorrect.
isarl is offline   Reply With Quote