Reshape list for table, flatten index in nested loops

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
# table.py -- tag and filter implementation
from django import template
from django.shortcuts import render_to_response
from django.template.loader import get_template

def reshape( lst, ncols, nrows, horiz=True ):
    """Change shape of list lst (like APL, J, K, NumPy).
    Return list of lists: ncols x nrows. horiz - is the
    table direction (horizontal or vertical if horiz is
    False). Empty cells will be with ''
    """
    if not ncols and not nrows: return lst

    w = ncols or len(lst)/nrows + (1 if len(lst)%nrows else 0)
    h = nrows or len(lst)/ncols + (1 if len(lst)%ncols else 0)
    
    if horiz:
        flatten = lambda irow, icol: icol + irow*w
    else:
        flatten = lambda irow, icol: irow + icol*h

    rows = []
    for irow in range( h ):
        col = []
        for icol in range( w ):
            iflat = flatten( irow, icol )
            el = '' if iflat >= len(lst) else lst[iflat]
            col.append( el )
        rows.append( col )

    return rows


register = template.Library()

@register.tag
def table( parser, token ):
    """ Push in context 'table_obj' object - list of lists, result
    of reshape function (see it)"""
    try:
        # lst - name of the list in the context, shape is string like 'H:4x?'|'V:2x2'|'?x3'
        # 'H' - horiz direction, 'V' - vertical direction, '?' - computable size, digit -
        # fixed size (see reshape function!)
        tag, lst, shape = token.split_contents()
    except ValueError:
        sx = 'tag %r requires two arguments'%token.contents[0]
        raise template.TemplateSyntaxError( sx )
    shape = shape[1:-1].upper() # cut .. from ".."
    if shape.startswith( 'V:' ):
        horiz = False
        shape = shape[2:]
    elif shape.startswith( 'H:' ):
        horiz = True
        shape = shape[2:]
    else:
        horiz = True
    w,h = shape.split( 'X' )
    w = None if w == '?' else int(w)
    h = None if h == '?' else int(h)
    if not h and not w:
        raise template.TemplateSyntaxError( 'only one axis may be unknown (?)' )

    nodes = parser.parse( ('endtable',) )
    parser.delete_first_token()
    return TableNode( nodes, lst, w, h, horiz )

class TableNode( template.Node ):
    def __init__( self, nodes, lst, w, h, horiz ):
        self.nodes = nodes
        self.lst = lst
        self.w = w
        self.h = h
        self.horiz = horiz
    def render( self, context ):
        # get list from context by it's name
        res = reshape( context[self.lst], self.w, self.h, self.horiz )
        context.push()
        context[ 'table_obj' ] = res
        txt = self.nodes.render( context )
        context.pop()
        return txt

@register.filter
def flatindex( forloop ):
    """Existed in the nested loops return flat index
    (index of flat list). For example:
    like in C N-th dimension array may look like
    flat array with ONE, flat index. This tag generate
    this flat index for nested loops in django template (see nested {% for...%})"""
    loop = forloop
    level = 0
    ret = 0
    nestedlen = 1
    while True:
        if level == 0:
            ret += loop['counter0']
            # length of current level * size of previous levels is
            # "weight" of ranking level. Ranking level add
            # nestedlen to flatindex if move by 1 (like hypercube).
            nestedlen *= loop['counter0'] + loop['revcounter0'] + 1 
        else:
            ret += loop['counter0']*nestedlen

        # go to next-up level
        parentloop = loop.get('parentloop', None)
        if parentloop:
            loop = parentloop
        else:
            break
        level += 1
    return ret

More like this

  1. Group sequence into rows and columns for a TABLE by davidwtbuxton 3 years, 2 months ago
  2. grouper tag by visgean 2 years, 8 months ago
  3. Yet another SQL debugging facility by miracle2k 6 years, 8 months ago
  4. Functional Filters by waterson 6 years, 7 months ago
  5. Sort Table Headers by insin 6 years, 9 months ago

Comments

(Forgotten your password?)