2011-12-29 10 views
3

アイテムが繰り返されていない10個のアイテム(値プリミティブ、オブジェクトではない)のスタックを保持する必要があります。ここに私の最初の刺す実装です。改善のための提案? JS 1.6、inArrayarray.indexOf(element) != -1のように書くことができるのでJavaScriptの非繰り返しスタック

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); 
} 
+0

私は同じメソッド内で 'new_item'と' newItem'を全く違うものに使うのは嫌いです。 – Douglas

+0

以前に[indexOf](https://developer.mozilla.org/ja/JavaScript/Reference/Global_Objects/Array/indexOf)を使用しましたか?私はあなたの 'inArray'メソッドを置き換えることができると思います。 – Douglas

+0

@Douglas:すべてのブラウザでサポートされているわけではありません。 IE 9で動作しないことを意味します。 –

答えて

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

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

として反復なしで書き込むことができます。

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

必要であればそうでない場合は、

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

はこのshim

while (i--) { 
    if (arr[i] === val) { 
     return true; 
    } 
} 
return false; 
+1

配列に 'indexOf'を使うのは、古いバージョンのIEでは(JSバージョンのために置いたように)うまく動作しませんが、Arrayオブジェクトにプロトタイプで追加すると簡単に追加できます。 – Deleteman

+1

@Deleteman:ここにあるように:https://developer.mozilla.org/ja/JavaScript/Reference/Global_Objects/Array/indexOf#Compatibility –

+0

素晴らしい提案。ありがとう! –

3
function inArray(arr, val) { 
    return !!~arr.indexOf(val); 
} 

ように、より簡単に書くことができ、私はこのようにホールド事を書き換えます:

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 
+0

'slice'は配列のコピーを返しますので、' items'にそれを割り当てなければなりません。 –

+0

母、 '!= -1'の' !!〜 'はまだ見たことがありません!効率的ではありませんが、コンパクトです... http://jsperf.com/bangbangwave – Amadan

+0

@AndrewHedgesは何を言ったのですか?また、 'addItem'に' len'を定義したこともありません。 – Amadan

-1

なぜヒープを使用しないのですか?あなたはO(n)の代わりにO(lg n)の挿入と削除を行うことができますが、それはそのままです。

+2

ヒープはスタックではないので、スタッフはその注文を保持する必要があるので?なぜなら、N <= 10のとき、O(log N)とO(N)はあまり関係ないからです。 – cHao

+0

@cHao:彼は提案された改善を求めていた。スタックの順序付けを維持できるようにヒープを変更できます。私はヒープの使用を提案しました。検索と挿入は、提供されたソリューションとは異なり、線形ではないからです。あなたは大丈夫ですが、Nが小さくても大丈夫ですが、これもまた改善されています。必ずしも「正しい答え」を与えているわけではありません。さらに、誰かが同じ質問をしてそれを検索し、Nが大きい場合、ヒープを使用することは、提供されたソリューションの線形制約を回避する正当な方法です。 – jzila

+0

スタックのプロパティを保持し、それでもヒープと呼ぶようにヒープを変更することはできません。 2つのデータ構造は根本的に異なります。スタックは定義上LIFOであり、ヒープは定義によるものではありません。それはスタックとしてハッシュテーブルを使用するようなものです。確かに、あなたはそれにスタックを束縛することができます(そして、挿入と削除はO(1)でさえあります)!しかし、そのプロセスでは、ハッシュテーブルとなるすべてを取り去ってしまいます。 – cHao

関連する問題