12

オブジェクトのアイテムを指定して、JavaScript オブジェクトを上下に移動したいと考えています。オブジェクトの例:

var items = {
   "5" : ["name", "link2"],
   "8" : ["name 2", "link 2"],
   "11" : ["name 3", "link 3"]
}

さて、アイテムを持っているとしますitems["8"]。前のアイテムと次のアイテムをそれぞれ取得したい。

getItemBefore = function(index) {
    // index holds 8
    // should return "5"
}

getItemAfter = function(index) {
    // index hold 8
    // should return 11
}

どうすればそれらのアイテムを入手できますか?

4

4 に答える 4

12

オブジェクトが保持するキーは、 を使用して配列として取得できますObject.keys(<var>)。配列内のキーの順序は任意です。インデックスを作成する前に並べ替える必要があります。オプションはsort()配列の組み込みメソッドで、カスタム比較関数を提供できるので特に便利です (以下を参照)。デフォルトの順序はアルファベット順です。

順序付けられた配列を取得したら、アイテムが配列内のどこにあるかを調べて、そこから次の要素と前の要素を返すだけです。

var keys = Object.keys(items).sort();
var loc = keys.indexOf(item);

次の場合loc > -1(つまり、アイテムが存在する場合):

  • 前の項目:items[keys[loc-1]]ですが、確認してくださいloc > 0(最初のものではありません)。
  • 次の項目:items[keys[loc+1]]ですが、確認してくださいloc < keys.length(最後の項目ではありません)。

Object.keysJavascript 1.85+ と互換性があります。これは、古いブラウザの回避策です。

代替注文

数値

キーに番号順を持たせたい場合は、次の比較関数を使用します。

var keys = Object.keys(items).sort( function(a,b) {
    return b - a;
});

作成 (または変更) 時間

英数字ではなく作成順序で作業する場合は、アイテムが作成時間を保持する必要があります。何かのようなもの:

<value>.index = Date.getTime();
items['<item>'] = <value>;

次に、sort()メソッドには次の比較関数が必要です。

var keys = Object.keys(items).sort( function(a,b) {
    return b.index - a.index;
});

これは、最終変更順序などに簡単に拡張できます。

作成順序

前者のソリューションは、アイテムが 1 ミリ秒以上離れて作成されている場合にのみ機能することに注意してください。これは、ユーザー アクションに適しています。アイテムがより速く追加される場合は、タイムスタンプの代わりにこれを使用します。

<value>.index = Object.keys(items).length;

または、代わりに、オブジェクト内のアイテムの数を外部カウンターに保持します。

于 2013-03-03T11:55:09.690 に答える
3

この回答は@lemonziの回答に基づいています。詳細な説明については、彼の回答を参照してください。

これに苦労しているすべての人に実際の例を追加したかっただけです:

var items = {
  "5": ["name", "link2"],
  "8": ["name 2", "link 2"],
  "11": ["name 3", "link 3"]
};

var getItem = function(key, i) {
  var keys = Object.keys(items).sort(function(a,b){return a-b;});
  var index = keys.indexOf(key);
  if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {index = index+i;}
  return items[keys[index]];
}

console.log(getItem("8",-1));
console.log(getItem("8",+1));
jsfiddle: https://jsfiddle.net/p09yL01f/3/

  • このように、アイテムを変更するために必要な関数は 1 つだけです。
  • .sort(function(a,b){return a-b;}) 、配列数値をソートします。
  • if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {、アイテムが配列内の最初または最後のインデックスではないことを確認し、そうである場合はインデックス自体を返します。

アイテムが最初または最後である場合にメッセージを表示する場合は、代わりにこれを使用します。

if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {return items[keys[index+i]];}
else {return (i==1?"last":"first")+" item";}

var items = {
  "5": ["name", "link2"],
  "8": ["name 2", "link 2"],
  "11": ["name 3", "link 3"]
};

var getItem = function(key, i) {
  var keys = Object.keys(items).sort(function(a,b){return a-b;});
  var index = keys.indexOf(key);
  if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {return items[keys[index+i]];}
  else {return (i==1?"last":"first")+" item";}
}

console.log(getItem("5",-1));
console.log(getItem("11",+1));
jsfiddle: https://jsfiddle.net/p09yL01f/4/

  • 三項演算子(i==1?"last":"first")と呼ばれます。それについて読んでください。
于 2016-11-12T16:18:15.153 に答える
2

技術的に ECMAScript 仕様によると、オブジェクト内のプロパティの順序は実装固有であるため、これは少し注意が必要です。つまり、アクセスするたびにプロパティが同じ順序になるという保証が言語にないということです。それに頼っていると、問題が発生する可能性があります。

Chrome でこのバグを参照してください。Chromeは特定の順序でキーを返すことを約束していないと述べており、4〜5年前から「WONTFIX」とマークされています. つまり、Chrome でその動作に依存することはできません。IE9 にも同じ「問題」があることを示す別の投稿があります。

そのため、独自のオブジェクトを作成してキーを管理し、バックグラウンドで JavaScript オブジェクトを使用してキーを保存することをお勧めします。

これは私が一緒に投げたものです。これは削除をサポートしておらず、境界チェックもありませんが、目的には役立つはずです。ここでフィドル

function orderedObject()
{
     this.keys = [];
     this.keyIndex = {};
     this.store = {};
}


orderedObject.prototype.addItem = function(key,value)
{
     this.keyIndex[key] = this.keys.length;
     this.keys.push(key);
     this.store[key] = value;
}

orderedObject.prototype.getItem = function(key)
{
     return this.store[key];
}

orderedObject.prototype.getKeyBefore = function(key)
{
     return this.keys[this.keyIndex[key] - 1];
}

orderedObject.prototype.getKeyAfter = function(key)
{
     return this.keys[this.keyIndex[key] + 1];
}

var testObject = new orderedObject();

testObject.addItem("5" , ["name", "link2"]);
testObject.addItem("8" , ["name 2", "link 2"]);
testObject.addItem("11" , ["name 3", "link 3"]);

console.log(testObject.getKeyBefore("8"))
console.log(testObject.getKeyAfter("8"))
于 2013-03-03T11:48:32.713 に答える
1

ここでは、オブジェクトの配列の方が適切でしょうか? 以下の例は、オブジェクトにラップして、nextItem() および prevItem() メソッドを作成することができます。これにより、いくつかの境界チェックも必要になる場合があります。

var items = [];
items[0] = {index : '5', name : 'name', link : 'link2'};
items[1] = {index : '8', name : 'name 2', link : 'link 2'};
items[2] = {index : '11', name : 'name 3', link : 'link 3'};

//then access them like this
var nextItem = function (index) {
    var i = 0,
    max = items.length;

    for (i; i < max; i += 1) {
        if (items[i].index === index) {
            return items[i + 1];
        }
    }
    return 'not found';
};

var prevItem = function (index) {
    var i = 0,
    max = items.length;

    for(i; i < max; i += 1) {
        if (items[i].index === index) {
            return items[i - 1];
        }
    }
    return 'not found';
};

//the nextItem object after 5 is shown in the console. 
console.dir(nextItem('5'));
于 2013-03-03T12:32:15.777 に答える