Search code examples
javascriptclassprototypal-inheritance

Let my class return array when doing Array.from


I have a PriorityQueue class, and it has many methods, such as add, peak, changePriority etc. So to instantiate the class we have:

let priorityQueue = new PriorityQueue();

To add something to a PriorityQueue instance, I can do something like this:

priorityQueue.add(10, 1);
priorityQueue.add(100, 0);
priorityQueue.add(200, 0);

My question is how can we do

Array.from(priorityQueue)

so that returns [100, 200, 10]?

Here is my complete code:

class QElement { 
    constructor(element, priority) 
    { 
        this.element = element; 
        this.priority = priority; 
    } 
} 
  
class PriorityQueue extends Array{ 
  
    // An array is used to implement priority 
    constructor() 
    { 
        super()
        this.items = []; 
    } 
    add(value, priority) 
    { 
        // creating object from queue element 
        var qElement = new QElement(value, priority); 
        var contain = false; 
      
        // iterating through the entire 
        // item array to add element at the 
        // correct location of the Queue 
        for (var i = 0; i < this.items.length; i++) { 
            if (this.items[i].priority > qElement.priority) { 
                // Once the correct location is found it is 
                // enqueued 
                this.items.splice(i, 0, qElement); 
                contain = true; 
                break; 
            } 
        } 
      
        // if the element have the highest priority 
        // it is added at the end of the queue 
        if (!contain) { 
            this.items.push(qElement); 
        } 
    }
    
    poll() 
    { 
        // return the dequeued element 
        // and remove it. 
        // if the queue is empty 
        // returns Underflow 
        if (this.isEmpty()) 
            return "Underflow"; 
        return this.items.shift(); 
    } 
    
    peak() 
    { 
        // returns the highest priority element 
        // in the Priority queue without removing it. 
        if (this.isEmpty()) 
            return "No elements in Queue"; 
        return this.items[0]; 
    } 
    
    rear() 
    { 
        // returns the lowest priorty 
        // element of the queue 
        if (this.isEmpty()) 
            return "No elements in Queue"; 
        return this.items[this.items.length - 1]; 
    }
    
    printPQueue() 
    { 
        var str = ""; 
        for (var i = 0; i < this.items.length; i++) 
            str += this.items[i].element + " "; 
        return str; 
    } 
}

var priorityQueue = new PriorityQueue();

priorityQueue.add(10, 1);
priorityQueue.add(100, 0);
priorityQueue.add(200, 0);
priorityQueue.printPQueue()
let ppp = Array.from(priorityQueue)
console.log(ppp)

This should return [100, 200, 10], but it returned [], an empty array.

I have to strictly use Array.from. What is the solution for this?


Solution

  • You could use Symbol.iterator.

    In the snippet below I have omitted any priority queue logic, and just used sort to demonstrate how that generator can be used:

    class PriorityQueue {
        constructor() {
            this.arr = [];
        }
        add(data, priority) {
            this.arr.push({ data, priority });
        }
        * [Symbol.iterator]() {
            yield * [...this.arr].sort((a, b) => a.priority - b.priority).map(a => a.data);
        }
    };
    
    let priorityQueue = new PriorityQueue();
    priorityQueue.add(10, 1);
    priorityQueue.add(100, 0);
    priorityQueue.add(200, 0);
    console.log(Array.from(priorityQueue));

    After edit

    The code you added to the question shows a mistake. Although you extend Array, you never make use of the Array capabilities of your instance. Your code continues as if it doesn't inherit those and instead creates an array property called items. It is to be expected when you push items to the items property that the this object will remain an empty array. If you want to use extends then you should have calls like this.push(value), this.pop() and this.splice(.....) somewhere.