Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
List library
#1
You can create lists (regular arrays but with added functionality) using this library if you want cleaner code.

list_example.n7
Code:
' list_example.n7
' ---------------

include "list.n7"

' Create a list.
list = List()

' Add(x) adds x to the end of the list.
list.Add("Hello")
list.Add("there")

' ToString() returns a string representation of the list.
pln "After Add: " + list.ToString()

' Insert(x, index) inserts x at a specified index.
list.Insert("everyone", 1)
pln "After Insert: " + list.ToString()

' Remove removes all occurrences of x from the list and returns the number of items removed.
list.Remove("Hello")
pln "After Remove: " + list.ToString()

' RemoveByIndex(index) removes the item at a specified index.
list.RemoveByIndex(0)
pln "After RemoveByIndex: " + list.ToString()

' Clear() clears the list.
list.Clear()
pln "After Clear: " + list.ToString()

' Add a bunch of random numbers.
for i = 1 to 10  list.Add(rnd(100))
pln "After Add: " + list.ToString()

' Sort(type) sorts the list. Use type list.ASCENDING to sort in ascending order.
list.Sort(list.ASCENDING)
pln "After Sort: " + list.ToString()

' Sorted(type) returns a sorted shallow copy of the list, this time in descending order. This does
' not affect the original list.
pln "Sorted clone: " + list.Sorted(list.DESCENDING).ToString()

' A function that returns a table with some information for a person.
function Person(name, age)
    p = [name: name, age: age]
    ' Add a ToString function. The list ToString function checks for function with this name and
    ' uses it in its own ToString function.
    p.ToString = function()
        return this.name + " (" + this.age + ")"
    endfunc
    return p
endfunc

' Clear the list and add some persons.
list.Clear()
list.Add(Person("Marcus", 43))
list.Add(Person("Sven", 28))
list.Add(Person("August", 13))
list.Add(Person("John", 76))
pln "After Add: " + list.ToString()
' SortByField(field, type) works like sort but sorts by a table field.
list.SortByField("age", list.DESCENDING)
pln "After SortByField: " + list.ToString()

' Add two more persons that have the same age as Marcus.
list.Add(Person("Alfons", 43))
list.Add(Person("Zara", 43))
' You can send your own sorting function to Sort/Sorted/SortByField/SortedByField. This function
' should take two parameters, like my_sorter(a, b). If a should come before b, return -1. If a
' should come after b, return 1. If a and b are equal, return 0. Here we use such a function to
' sort our persons first by age and then by name.
list.Sort(function(a, b)
        ' By age.
        if a.age < b.age  return -1
        if a.age > b.age  return 1
        ' Then by name.
        if a.name < b.name  return -1
        if a.name > b.name  return 1
        return 0
    endfunc)
pln "After Add and Sort by age and name: " + list.ToString()

' Pop removes and returns the last item in the list.
person = list.Pop()
' You can use Contains(x) to check if the list contains x. You can also use IndexOf(x) to get the
' index of the first occurrence of x in the list or IndexOfFrom(x, i) to return the first occurrence
' of x from index i. IndexOf and IndexOfFrom returns -1 if x does not exist in the list.
if list.Contains(person)  pln person.ToString() + " is still in the list"
else  pln person.ToString() + " is no longer in the list"

' You can access the elements of the list as you do with a regular array. But you can NOT use sizeof
' to determine the size of a list (sizeof would return the number of fields in the list, including
' its functions). Use the Size() function or access the field size directly.
pln "Forward iteration:"
for i = 0 to list.Size() - 1  pln "  " + list[i].ToString()
pln "Backward iteration:"
for i = list.size - 1 to 0  pln "  " + list[i].ToString()

system "pause"

list.n7
Code:
' List.n7
' -------
' Just an array with some helper functions.


' List
' ----
' Return a new List.
function List()
    list = []
    list.size = 0
    list.ASCENDING = 1
    list.DESCENDING = -1

    ' Size
    ' ----
    ' Return size. Accessing the size field is okay.
    list.Size = function()
        return this.size
    endfunc

    ' Contains
    ' --------
    ' Return true if list contains x.
    list.Contains = function(x)
        if not this.size  return false
        for i = 0 to this.size - 1  if this[i] = x  return true
        return false
    endfunc

    ' IndexOf
    ' -------
    ' Return index of first occurrance of x in list or -1 if x wasn't found.
    list.IndexOf = function(x)
        if this.size  for i = 0 to this.size - 1  if this[i] = x  return i
        return -1
    endfunc
   
    ' IndexOfFrom
    ' -----------
    ' Return index of first occurance of x in list, starting the search at index index, or -1 if x
    ' wasn't found.
    list.IndexOfFrom = function(x, index)
        if index < 0 or index >= this.size  return -1
        for i = index to this.size - 1  if this[i] = x  return i
        return -1
    endfunc

    ' Clone
    ' -----
    ' Return a shallow clone of this list. For a deep copy, just use the copy command.
    list.Clone = function()
        list = List()
        if this.size  for i = 0 to this.size - 1  list.Add(this[i])
        return list
    endfunc

    ' Clear
    ' -----
    ' Clear list.
    list.Clear = function()
        if not this.size  return false
        for i = 0 to this.size - 1  free this[i]
        this.size = 0
        return true
    endfunc
           
    ' Add
    ' ---
    ' Add x at the end of the list.
    list.Add = function(x)
        this[this.size] = x
        this.size = this.size + 1
    endfunc
   
    ' AddList
    ' -------
    ' Add the content of list to end of this list.
    list.AddList = function(list)
        if not list.size  return
        for i = 0 to list.size - 1  this[this.size + i] = list[i]
        this.size = this.size + list.size
    endfunc
   
    ' Insert
    ' ------
    ' Insert x at index index.
    list.Insert = function(x, index)
        ' Should index be cropped? I think it's better to assert.
        assert index >= 0 and index <= this.size, "List.Insert: Invalid index " + index
        if index < this.size  for i = this.size - 1 to index  this[i + 1] = this[i]
        this[index] = x
        this.size = this.size + 1
    endfunc
   
    ' Remove
    ' ------
    ' Remove x from the list.
    list.Remove = function(x)
        if not this.size  return 0
        sub = 0
        for i = 0 to this.size - 1
            if this[i] = x
                free this[i]
                sub = sub + 1
            else
                this[i - sub] = this[i]
            endif
        next
        this.size = this.size - sub
    endfunc
   
    ' RemoveByIndex
    ' -------------
    ' Remove index index from list.
    list.RemoveByIndex = function(index)
        if index < 0 or index >= this.size  return false
        free this[index]
        if index < this.size - 1  for i = index to this.size - 2  this[i] = this[i + 1]
        this.size = this.size - 1
        return true
    endfunc

    ' Pop
    ' ---
    ' Remove and return the last item in the list.
    list.Pop = function()
        if not this.size  return unset
        this.size = this.size - 1
        x = this[this.size]
        free this[this.size]
        return x
    endfunc
           
    ' Sort
    ' ----
    ' Sort list using quick sort, type can be list.ASCENDING, list.DESCENDING or a function. If a
    ' function is used, it should take two arguments, like my_sorter(a, b). If a should come before
    ' b the function must return a negative value (like -1). If a should come after b, return a
    ' positive number. If a and b are equal, return 0.
    list.Sort = function(type)
        ' Sort ascending.
        function reclh(a, low, high)
            i = low; j = high
            pivot = a[(low + high)/2]
            do
                while (a[i] < pivot)  i = i + 1
                while (a[j] > pivot)  j = j - 1
                if i <= j
                    tmp = a[i]; a[i] = a[j]; a[j] = tmp
                    i = i + 1; j = j - 1
                endif
            until i > j
            if low < j  reclh(a, low, j)
            if i < high  reclh(a, i, high)
        endfunc
   
        ' Sort descending.
        function rechl(a, low, high)
            i = low; j = high
            pivot = a[(low + high)/2]
            do
                while (a[i] > pivot)  i = i + 1
                while (a[j] < pivot)  j = j - 1
                if i <= j
                    tmp = a[i]; a[i] = a[j]; a[j] = tmp
                    i = i + 1; j = j - 1
                endif
            until i > j
            if low < j  rechl(a, low, j)
            if i < high  rechl(a, i, high)
        endfunc
   
        ' Sort using function f.
        function recf(a, low, high, f)
            i = low; j = high
            pivot = a[(low + high)/2]
            do
                while f(a[i], pivot) < 0  i = i + 1
                while f(a[j], pivot) > 0  j = j - 1
                if i <= j
                    tmp = a[i]; a[i] = a[j]; a[j] = tmp
                    i = i + 1; j = j - 1
                endif
            until i > j
            if low < j  recf(a, low, j, f)
            if i < high  recf(a, i, high, f)
        endfunc
   
        if this.size > 1
            if typeof(type) = TYPE_FUNCTION  recf(this, 0, this.size - 1, type)
            elseif type >= 0  reclh(this, 0, this.size - 1)
            else rechl(this, 0, this.size - 1)
        endif
    endfunc
   
    ' Sorted
    ' ------
    ' Works like Sort, but returns a sorted shallow copy instead of sorting this list.
    list.Sorted = function(type)
        list = this.Clone()
        list.Sort(type)
        return list
    endfunc

    ' SortByField
    ' -----------
    ' Works like Sort but compares a field f of the items in the list.
    list.SortByField = function(f, type)
        ' Sort ascending.
        function reclh(a, f, low, high)
            i = low; j = high
            pivot = a[(low + high)/2][f]
            do
                while (a[i][f] < pivot)  i = i + 1
                while (a[j][f] > pivot)  j = j - 1
                if i <= j
                    tmp = a[i]; a[i] = a[j]; a[j] = tmp
                    i = i + 1; j = j - 1
                endif
            until i > j
            if low < j  reclh(a, f, low, j)
            if i < high  reclh(a, f, i, high)
        endfunc
   
        ' Sort descending.
        function rechl(a, f, low, high)
            i = low; j = high
            pivot = a[(low + high)/2][f]
            do
                while (a[i][f] > pivot)  i = i + 1
                while (a[j][f] < pivot)  j = j - 1
                if i <= j
                    tmp = a[i]; a[i] = a[j]; a[j] = tmp
                    i = i + 1; j = j - 1
                endif
            until i > j
            if low < j  rechl(a, f, low, j)
            if i < high  rechl(a, f, i, high)
        endfunc
   
        ' Sort using function f.
        function recf(a, f, low, high, fn)
            i = low; j = high
            pivot = a[(low + high)/2][f]
            do
                while fn(a[i][f], pivot) < 0  i = i + 1
                while fn(a[j][f], pivot) > 0  j = j - 1
                if i <= j
                    tmp = a[i]; a[i] = a[j]; a[j] = tmp
                    i = i + 1; j = j - 1
                endif
            until i > j
            if low < j  recf(a, f, low, j, fn)
            if i < high  recf(a, f, i, high, fn)
        endfunc
   
        if this.size > 1
            if typeof(type) = TYPE_FUNCTION  recf(this, f, 0, this.size - 1, type)
            elseif type >= 0  reclh(this, f, 0, this.size - 1)
            else rechl(this, f, 0, this.size - 1)
        endif
    endfunc

    ' SortedByField
    ' -------------
    ' Works like SortByField, but returns a sorted shallow copy instead of sorting this list.
    list.SortedByField = function(f, type)
        list = this.Clone()
        list.SortByField(f, type)
        return list
    endfunc
           
    ' ToString
    ' --------
    ' Return a string version of the list. If any item in the list is a table with a ToString
    ' function, the function will be called to get a string representation for that item.
    list.ToString = function()
        s = "["
        if this.size > 0
            for i = 0 to this.size - 1
                if typeof(this[i]) = TYPE_TABLE and key(this[i], "ToString") and
                        typeof(this.ToString) = TYPE_FUNCTION
                    if i = 0  s = s + this[i].ToString()
                    else s = s + ", " + this[i].ToString()
                else
                    if i = 0  s = s + this[i]
                    else s = s + ", " + this[i]
                endif
            next
        endif
        return s + "]"
    endfunc
   
    return list
endfunc
Reply
#2
This is incredible, with this the programming will be easier in naalaa, thanks Marcus.

I think you should add this in the naalaa language and add the appropriate documentation in the manual, this seems too important to me to be lost here in the forum. Greetings  Smile
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)