Chapter 7
yield from rank_data(tuple(seq_or_iter), key)
data = seq_or_iter
head= seq_or_iter[0]
Convert to Rank_Data and process.
if not isinstance(head, Rank_Data):
ranked= tuple(Rank_Data((),d) for d in data)
for r, rd in rerank(ranked, key):
yield Rank_Data(rd.rank_seq+(r,), rd.raw)
return
Collection of Rank_Data is what we prefer.
for r, rd in rerank(data, key):
yield Rank_Data(rd.rank_seq+(r,), rd.raw)
We've decomposed the ranking into three cases for three different types of data.
We're forced it to do this when the different kinds of data aren't polymorphic
subclasses of a common superclass. The following are the three cases:
- Given an iterable (without a usable getitem() method), we'll
materialize a tuple that we can work with - Given a collection of some unknown type of data, we'll wrap the unknown
objects into Rank_Data tuples - Finally, given a collection of Rank_Data tuples, we'll add yet another ranking
to the tuple of ranks inside the each Rank_Data container
This relies on a rerank() function that inserts and returns another ranking into
the Rank_Data tuple. This will build up a collection of individual rankings from
a complex record of raw data values. The rerank() function follows a slightly
different design than the example of the rank() function shown previously.
This version of the algorithm uses sorting instead of creating a groups in a objects
like Counter object:
def rerank(rank_data_collection, key):
sorted_iter= iter(sorted( rank_data_collection, key=lambda
obj: key(obj.raw)))
head = next(sorted_iter)
yield from ranker(sorted_iter, 0, [head], key)
We've started by reassembling a single, sortable collection from the head and the
data iterator. In the context in which this is used, we can argue that this is a bad idea.