3

I need to keep a stack of 10 items (value primitives, not objects) where no item is repeated. Here's my initial stab at an implementation. Any suggestions for improvements?

var items = [];

function newItem() {
    return Math.floor(Math.random() * 50);
}

function inArray(arr, val) {
    var in_arr, i;
    in_arr = false;
    i = arr.length;
    if (i < 1) {
        return in_arr;
    }
    do {
        if (arr[i - 1] === val) {
            in_arr = true;
            break;
        }
    } while (--i);
    return in_arr;
}

function addItem() {
    var new_item;
    while (items.length > 9) {
        items.shift();
    }
    do {
        new_item = newItem();
    } while (inArray(items, new_item));
    items.push(new_item);
}
4
  • I don't like the use of new_item and newItem in the same method to mean quite different things. Commented Dec 29, 2011 at 19:21
  • Have you used indexOf before? I think it could replace your inArray method. Commented Dec 29, 2011 at 19:23
  • @Douglas: Not all browsers support it. By that I mean it doesn't work on IE < 9. Commented Dec 29, 2011 at 19:26
  • Good point - though then it is a trade off between using the implementation on that page, or your own one. Commented Dec 29, 2011 at 20:13

3 Answers 3

5
while (items.length > 9) {
    items.shift();
}

can be written without iteration as

var len = items.length;
if (len > 9) {
    items = items.slice(len - 9);
}

Since JS 1.6, inArray can be written as array.indexOf(element) != -1. Otherwise,

if (i < 1) {
    return in_arr;
}
do {
    if (arr[i - 1] === val) {
        in_arr = true;
        break;
    }
} while (--i);
return in_arr;

can be written more simply as

while (i--) {
    if (arr[i] === val) {
        return true;
    }
}
return false;
Sign up to request clarification or add additional context in comments.

2 Comments

Using indexOf for arrays won't work for older versions of IE (as you put it, because of the JS version), but can easily be added by prototyping it into the Array object.
3
function inArray(arr, val) {
    return !!~arr.indexOf(val);
}

with this shim if needed

function addItem(item) {
    if (inArray(items, item)) return false;
    if (items.length > 9) items = items.slice(len - 9);
    items.push(item);
    return true;
}

I would rewrite the hold thing like this:

function stack10() {
    var items = arguments || [];
    this.addItem = function (item) {
        var len = items.length;
        if (!!~items.indexOf(item)) return;
        if (len > 9) items = items.slice(len - 9);
        items.push(item);
    } 
    this.peek = function() {
        if (items.length === 0) return null;
        return items[items.length-1];
    }
    this.pop = function () {
        return items.pop();
    }
}
var myStack = new stack10();
myStack.addItem(10);
myStack.peek(); // 10
myStack.pop(); // 10
myStack.pop(); // undefined

// default values
var myStack2 = new stack10(1,2,3,4);
myStack2.addItem(10);
myStack2.peek(); // 10
myStack2.pop(); // 10
myStack2.pop(); // 4

4 Comments

slice returns a copy of the array, so you have to assign it back to items, otherwise, this looks good.
Haha, never seen !!~ for != -1 yet! Not as efficient, but damn compact... jsperf.com/bangbangwave
What @AndrewHedges said; also, you never defined len in addItem.
@Amadan, thanks. I updated. I think your solution is more complete/friendly anyways.
-1

Why not use a heap? You can do O(lg n) insert and removal instead of O(n), and it's still in-place.

6 Comments

Because a heap is not a stack? Because stuff needs to retain its order? Because O(log N) and O(N) don't matter so much when N <= 10?
@cHao: He was asking for suggested improvements. You can modify a heap such that you can maintain stack ordering. I suggested the use of a heap since search and insertion are sub-linear, unlike the provided solution. You're right that big-O doesn't matter when N is small, but yet again: this is about suggested improvements, not necessarily giving "The Right Answer". Additionally, if someone has this same question and searches for it, but with large N, using a heap is a legitimate way of getting around the linear constraints of the provided solution.
You can't modify a heap such that it retains properties of a stack, and still call it a heap. The two data structures are fundamentally different; stacks are by definition LIFO, and heaps are by definition...not. It'd be like using a hash table as a stack. Sure, you could shoehorn a stack into it (and insertion and removal would even be O(1)!), but in the process you'd be taking away everything that makes it a hash table.
For my use case, order is important.
Plus, the constraints of the problem make O(log N) all but impossible anyway -- attempting to add X would require searching the collection for X, making adding an element O(N) at best. You can compare items by insertion order or by value, but doing both would require two heaps.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.