Table<T> 2d array


Tweet monkey-x code-archives algorithms
(Posted 6 months ago) RonTek

A convenient 2d array with neat features.

Features include the ability to get/set/iterate through individual rows or columns, native 1d data access, 2d data accessors (Get/Set), and support for exceptions to prevent undefined behavior on the desktop target.

Author: Nobuyuki

table.monkey

Class Table<T>
    Field Width:Int, Height:Int
    Field data:T[]

    'Summary:  Creates a new data table of the specified size.
    Method New(width:Int, height:Int)
        If width <= 0 or height <= 0
            Print("Warning:  Table of invalid dimensions defined. (" + width + "," + height + ")")
            Throw New TableInitError()
        Else
            Width = width; Height = height
            data = data.Resize(width * height)
        End If
    End Method

    'Summary:  Returns the table to uninitialized values.
    Method Clear:Void()
        'I wonder if this is a good idea
        Local newdata:T[]
        newdata = newdata.Resize(Width * Height)
        data = newdata
    End Method

    'Summary:  Returns the value at (x,y).
    Method Get:T(x:Int, y:Int)
        #If CONFIG="debug"
            If (0 > x) Or (x >= Width) Then Print("Warning: X is out of range. " + x)
            If (0 > y) Or (y >= Height) Then Print("Warning: Y is out of range. " + y)
            If (0 > x) Or (x >= Width) Or (0 > y) Or (y >= Height)
                Throw New TableIndexOutOfRangeError()
            End If
        #EndIf 

        Return data[y * Width + x]
    End Method

    'Summary:  Sets the value at (x,y).
    Method Set:Void(value:T, x:Int, y:Int)
        #If CONFIG="debug" 
            If (0 > x) Or (x >= Width) Then Print("Warning: X is out of range. " + x)
            If (0 > y) Or (y >= Height) Then Print("Warning: Y is out of range. " + y)
            If (0 > x) Or (x >= Width) Or (0 > y) Or (y >= Height)
                Throw New TableIndexOutOfRangeError()
            End If
        #EndIf 

        data[y * Width + x] = value
    End Method


    'Summary:  Returns an array representing a row in the table structure.  
    Method Row:T[] (index:Int)
        If (0 > index) Or (index >= Height) Then Throw New TableIndexOutOfRangeError()

        Local out:T[]
        out = out.Resize(Width)

        For Local i:Int = 0 Until Width
            out[i] = data[ (index * Width) + i]
        Next

        Return out
    End Method
    'Summary:  Returns an array representing a column in the table structure.   
    Method Column:T[] (index:Int)
        If (0 > index) Or (index >= Width) Then Throw New TableIndexOutOfRangeError()

        Local out:T[]
        out = out.Resize(Height)

        For Local i:Int = 0 Until Height
            out[i] = data[ (i * Width) + index]
        Next

        Return out      
    End Method

    'Summary:  Sets a row of values to the ones in [value].
    Method SetRow:Void(value:T[], index:Int)
        For Local i:Int = 0 Until Width
             data[ (index * Width) + i] = value[i]
        Next        
    End Method
    'Summary:  Sets a column of values to the ones in [value].
    Method SetColumn:Void(value:T[], index:Int)
        For Local i:Int = 0 Until Height
            data[ (i * Width) + index] = value[i]
        Next        
    End Method


    'Summary:  Provides an object enumerating all rows in the table.
    Method Rows:TableRows<T>()
        Return New TableRows<T>(Self)
    End Method
    'Summary:  Provides an object enumerating all columns in the table.
    Method Columns:TableColumns<T>()
        Return New TableColumns<T>(Self)
    End Method

End Class

'Summary:  Thrown when table doesn't init correctly.
Class TableInitError Extends Throwable  
End Class
'Summary:  Thrown when a row or column value is out of range.
Class TableIndexOutOfRangeError Extends Throwable
End Class

'The below classes are for allowing EachIn enumeration of rows and columns.
'#Region Row/Column Enumerators
Class TableRows<T>
  Private
    Field table:Table<T>

  Public
    Method New(table:Table<T>)
        Self.table = table
    End

    Method ObjectEnumerator:RowEnumerator<T>()
        Return New RowEnumerator<T>(table)
    End 
End Class

Class TableColumns<T>
  Private
    Field table:Table<T>

  Public
    Method New(table:Table<T>)
        Self.table = table
    End

    Method ObjectEnumerator:ColumnEnumerator<T>()
        Return New ColumnEnumerator<T>(table)
    End     
End Class


Class RowEnumerator<T>
  Private
    Field table:Table<T>
    Field index:Int

  Public
    Method New(table:Table<T>)
        Self.table = table
    End Method

    Method HasNext:Bool()
        Return index < table.Height
    End Method

    Method NextObject:T[] ()
        index+=1
        Return table.Row(index - 1)
    End Method
End Class

Class ColumnEnumerator<T>
  Private
    Field table:Table<T>
    Field index:Int

  Public
    Method New(table:Table<T>)
        Self.table = table
    End Method

    Method HasNext:Bool()
        Return index < table.Width
    End Method

    Method NextObject:T[] ()
        index+=1
        Return table.Column(index - 1)
    End Method
End Class
'#End Region

Example

Import table

Function Main:Int()
    'Makes a 5x5 table
    Local t:=New Table<Int>(5,5)  

    'Initialize each cell in a row to the same value?
    Local rowNum:Int
    For local row:= EachIn t.Rows()
        For local i:Int = 0 until t.Width 'We could've also said eachIn row, or until row.Length()
            row[i] = rowNum
        Next 
        rowNum+=1
    Next 

    'Randomize the entire table.
    For local i:Int = 0 until t.data.Length
        t.data[i] = Rnd($FFFFFFF)
    Next 

    'Gimme a copy of column 3.
    Local col:Int[] = t.Column(3)

    'Let's change all of column 3 to 0.
    For local i:Int = 0 until col.Length
        col[i] = 0
    Next 
    t.SetColumn(col, 3)

    'Catching an out of range index.
    Try
        Local invalid:Int = t.Get(-1,-1)
    Catch ex:TableIndexOutOfRangeError
        Print ("Invalid cell!")
    End Try 
End Function

Reply To Topic (minimum 10 characters)

Please log in to reply