Pawel Chmielowski - List.Prioritized-0.01

Documentation | Source

NAME

List.Prioritized - List which sorts elements by prirority

SYNOPSIS

    // Import List.Prioritized module.
    JSAN.use('List.Prioritized');

    var list = new List.Prioritized();

    list.insert("B", 2);
    list.insert("A", 1);
    list.insert("C", 3);

    for (var i = 0; i < list.length; i++)
        alerty(list[i]) // gives A, B and C

    list.remove("A");
    list.removeAt(1);

    alert(list[0]+", "+list.length); // gives "B, 1"

    var list2 = new List.Prioritized();

    list.insert("A", 1);
    list.insert("D", 4);
    list2.insert("C", 3);
    list2.insert("0", 0);

    var i = new List.Prioritized.Iterator(list, list2);

    while (i.hasNext())
        alert(i.getNext()) // gives 0, A, B, C, D

    i.reset();
    alert(i.getNext()) // gives 0

DESCRIPTION

This module defines class which adds list with elements sorted by priority.

CLASSES

List.Prioritized class

This class implements list which keeps its elements sorted by priority value. It has interface simmilar to standard Array, but it only allows to add elements by insert() method (standard Array methods which can be used for this purpose like push() or unshift() throws exceptions in this class).

new List.Prioritized()

Create new object. It takes no arguments.

list.insert(ITEM, PRIORITY)

Add new element ITEM with priority PRIORITY to this list.

Returns ITEM

list.remove(ITEM)

Remove ITEM from list.

Returns index of removed element or null when none elements was removed.

list.push()

This operation cannot be used in this class, it throws exception.

list.unshift()

This operation cannot be used in this class, it throws exception.

list.pop()

It works like Array.pop() but also change internal structure.

list.shift()

It works like Array.pop() but also change internal structure.

list.splice()

Works simmilar to Array.splice() but only two argument version is supported. When called with > 2 arguments this method throws exception.

List.Prioritized.Iterator class

Define List.Prioritized iteratior class. It can be used to iterate List.Iterator lists in priority order.

It can iterate one or more list simultaneously.

new List.Prioritized.Iterator([LIST1, [LIST2, ...]])

Create new iterator which will process all elements of LIST1, LIST2... in priority order.

iterator.hasNext()

Checks that next element is avaialble. Returns false when all elements was already processed, true otherwise.

iterator.getNext()

Return next element and increment internal index counter.

When all elements was already processed returns undefined.

iterator.reset()

Reset internal index counter to initial value. All further getNext() operations will be processed from start of the list.

CAVEATS and NOTES

  • Only iterators for 1, 2 or 3 lists are implemented

AUTHOR

Pawel Chmielowski <prefiks@aviary.pl>

COPYRIGHT

  Copyright (c) 2005 Pawel Chmielowski. All rights reserved.
  This module is free software; you can redistribute it and/or modify it
  under the terms of the LGPL license.
/*

=head1 NAME

List.Prioritized - List which sorts elements by prirority

=head1 SYNOPSIS

    // Import List.Prioritized module.
    JSAN.use('List.Prioritized');

    var list = new List.Prioritized();

    list.insert("B", 2);
    list.insert("A", 1);
    list.insert("C", 3);

    for (var i = 0; i < list.length; i++)
        alerty(list[i]) // gives A, B and C

    list.remove("A");
    list.removeAt(1);

    alert(list[0]+", "+list.length); // gives "B, 1"

    var list2 = new List.Prioritized();

    list.insert("A", 1);
    list.insert("D", 4);
    list2.insert("C", 3);
    list2.insert("0", 0);

    var i = new List.Prioritized.Iterator(list, list2);

    while (i.hasNext())
        alert(i.getNext()) // gives 0, A, B, C, D

    i.reset();
    alert(i.getNext()) // gives 0

=head1 DESCRIPTION

This module defines class which adds list with elements sorted by priority.

=cut

*/

if (!this.List) List = {};

if (!List.Prioritized) {
/*

=head1 CLASSES

=head2  List.Prioritized class

This class implements list which keeps its elements sorted by priority value. It
has interface simmilar to standard Array, but it only allows to add elements by
insert() method (standard Array methods which can be used for this purpose like
push() or unshift() throws exceptions in this class).

=head3 new List.Prioritized()

Create new object. It takes no arguments.

=cut

*/
    List.Prioritized = function() {
        this._priorities = [];
    }

    List.Prioritized.prototype =
    {
        VERSION: "0.01",
        __proto__: Array.prototype,
/*

=head3 list.insert(ITEM, PRIORITY)

Add new element ITEM with priority PRIORITY to this list.

Returns ITEM

=cut

*/
        insert: function(item, priority)
        {
            var a = 0;
            var b = this.length-1;
            var mid, val;

            priority = priority || 0;

            if (b < 0 || priority > this._priorities[b])
                a = this.length;
            else {
                do {
                    mid = a + ((b-a)>>1);
                    if (priority < this._priorities[mid])
                        b = mid-1;
                    else if (priority > this._priorities[mid])
                        a = mid+1;
                    else {
                        a = mid;
                        break;
                    }
                } while (a <= b);
            }

            Array.prototype.splice.call(this, a, 0, item);
            this._priorities.splice(a, 0, priority);

            return item;
        },

/*

=head3 list.remove(ITEM)

Remove ITEM from list.

Returns index of removed element or C<null> when none elements was removed.

=cut

*/
        remove: function(item)
        {
            var i;
            for (i = 0; i < this.length; i++)
                if (this[i] == item) {
                    Array.prototype.splice.call(this, i, 1);
                    this._priorities.splice(i, 1);

                    return i;
                }
            return null;
        },

/*

=head3 list.push()

This operation cannot be used in this class, it throws exception.

=cut

*/
        push: function()
        {
            throw "You cannot use push() on List.Prioritized"
        },

/*

=head3 list.unshift()

This operation cannot be used in this class, it throws exception.

=cut

*/
        unshift: function()
        {
            throw "You cannot use unshift() on List.Prioritized"
        },

/*

=head3 list.pop()

It works like Array.pop() but also change internal structure.

=cut

*/
        pop: function()
        {
            this._priorities.pop();
            return Array.prototype.pop.call(this)
        },

/*

=head3 list.shift()

It works like Array.pop() but also change internal structure.

=cut

*/
        shift: function()
        {
            this._priorities.shift();
            return Array.prototype.shift.call(this)
        },

/*

=head3 list.splice()

Works simmilar to Array.splice() but only two argument version is supported.
When called with > 2 arguments this method throws exception.

=cut

*/
        splice: function(index, howMany)
        {
            if (arguments.length > 2)
                throw "You cannot use splice() on List.Prioritized to change some elements";

            this._priorities.splice(index, howMany);
            return Array.prototype.splice.call(this, index, howMany);
        },
    }

/*

=head2 List.Prioritized.Iterator class

Define List.Prioritized iteratior class. It can be used to iterate
List.Iterator lists in priority order.

It can iterate one or more list simultaneously.

=head3 new List.Prioritized.Iterator([LIST1, [LIST2, ...]])

Create new iterator which will process all elements of LIST1, LIST2...
in priority order.

=cut

*/
    List.Prioritized.Iterator = function()
    {
        var i, r = [];

        for (i = 0; i < arguments.length; i++)
            if (arguments[i] && arguments[i].length)
                r.push(arguments[i]);

        switch (r.length) {
        case 0:
            return List.Prioritized._emptyIterator;
        case 1:
            break;
        case 2:
            return new List.Prioritized._Iterator2(r[0], r[1]);

        case 3:
            return new List.Prioritized._Iterator3(r[0], r[1], r[2]);

        default:
            return new List.Prioritized._IteratorMulti(r);
        }

        this.plist = r[0];
        this.i = 0;
    }

    List.Prioritized.Iterator.prototype =
    {
/*

=head3 iterator.hasNext()

Checks that next element is avaialble. Returns C<false> when all elements was
already processed, C<true> otherwise.

=cut

*/
        hasNext: function()
        {
            return this.plist.length > this.i;
        },

/*

=head3 iterator.getNext()

Return next element and increment internal index counter.

When all elements was already processed returns C<undefined>.

=cut

*/
        getNext: function()
        {
            return this.plist[this.i++];
        },

/*

=head3 iterator.reset()

Reset internal index counter to initial value. All further getNext()
operations will be processed from start of the list.

=cut

*/
        reset: function()
        {
            this.i = 0;
        }
    }

    List.Prioritized._emptyIterator =
    {
        hasNext: function()
        {
            return false;
        },

        getNext: function()
        {
            return null
        },

        reset: function()
        {
        }
    }

    List.Prioritized._Iterator2 = function(plist1, plist2)
    {
        if (arguments.length > 2)
            return new PlistCompositeIteratorMulti(arguments);
        this.p1 = plist1;
        this.p2 = plist2;
        this.i1 = 0;
        this.i2 = 0;
    }

    List.Prioritized._Iterator2.prototype =
    {
        hasNext: function()
        {
            return this.p1.length > this.i1 || this.p2.length > this.i2;
        },

        getNext: function()
        {
            if (this.p1.length <= this.i1)
                return this.p2[this.i2++];
            if (this.p2.length <= this.i2)
                return this.p1[this.i1++];
            if (this.p1._priorities[this.i1] > this.p2._priorities[this.i2])
                return this.p2[this.i2++];
            return this.p1[this.i1++];
        },

        reset: function()
        {
            this.i1 = this.i2 = 0;
        }
    }
    
    List.Prioritized._Iterator3 = function(plist1, plist2, plist3)
    {
        this.p1 = plist1;
        this.p2 = plist2;
        this.p3 = plist3;
        this.i1 = 0;
        this.i2 = 0;
        this.i3 = 0;
    }

    List.Prioritized._Iterator3.prototype =
    {
        hasNext: function()
        {
            return this.p1.length > this.i1 || this.p2.length > this.i2 ||
                this.p3.length > this.i3;
        },

        getNext: function()
        {
            if (this.p1.length <= this.i1)
                if (this.p2.length <= this.i2)
                    return this.p3[this.i3++];
                else
                    if (this.p3.length <= this.i3)
                        return this.p2[this.i2++];
                    else
                        if (this.p2._priorities[this.i2] > this.p3._priorities[this.i3])
                            return this.p3[this.i3++];
                        else
                            return this.p2[this.i2++];
            else
                if (this.p2.length <= this.i2)
                    if (this.p3.length <= this.i3)
                        return this.p1[this.i1++];
                    else
                        if (this.p1._priorities[this.i1] > this.p3._priorities[this.i3])
                            return this.p3[this.i3++];
                        else
                            return this.p1[this.i1++];
                else
                    if (this.p3.length <= this.i3)
                        if (this.p1._priorities[this.i1] > this.p2._priorities[this.i2])
                            return this.p2[this.i2++];
                        else
                            return this.p1[this.i1++];
                    else
                        if (this.p1._priorities[this.i1] > this.p2._priorities[this.i2])
                            if (this.p2._priorities[this.i2] > this.p3._priorities[this.i3])
                                return this.p3[this.i3++];
                            else
                                return this.p2[this.i2++];
                        else
                            if (this.p1._priorities[this.i1] > this.p3._priorities[this.i3])
                                return this.p3[this.i3++];
                            else
                                return this.p1[this.i1++];
        },

        reset: function()
        {
            this.i1 = this.i2 = this.i3 = 0;
        }
    }

    List.Prioritized._IteratorMulti = function(args)
    {
        throw "Multi argument iterator not implemented.";
    }
}

/*

=head1 CAVEATS and NOTES

=over 2

=item * Only iterators for 1, 2 or 3 lists are implemented

=back

=head1 AUTHOR

Pawel Chmielowski <F<prefiks@aviary.pl>>

=head1 COPYRIGHT

  Copyright (c) 2005 Pawel Chmielowski. All rights reserved.
  This module is free software; you can redistribute it and/or modify it
  under the terms of the LGPL license.

=cut

*/