25

キーが与えられたら、オブジェクト内の次のプロパティを見つけたいと思います。順序付けまたは順次のキーに依存することはできません(それらはuuidです)。私が欲しいものの簡単な例については、以下を参照してください。

var db = {
  a: 1,
  b: 2,
  c: 3
}

var next = function(db, key) {
  // ???
}

next(db, 'a');  // I want 2
next(db, 'b');  // I want 3

prev()関数も必要ですが、同じ解決策になると確信しています。

これはとても些細な問題のように思えますが、私はそれをどのように行うかを一生理解することができません。

underscore.jsを使用するか、coffeescriptで記述されるソリューションに満足しています:)

4

6 に答える 6

24

ts/es6バージョン。storeObjectからキーを取得し、次のインデックスを探します。

 let keys = Object.keys(storeObject);
 let nextIndex = keys.indexOf(theCurrentItem) +1;
 let nextItem = keys[nextIndex];
于 2017-10-25T22:26:22.927 に答える
22

正解は次のとおりです。オブジェクトはECMAScriptの仕様に従って順序付けされていないため、これを行うことはできません。

問題の目的のために、配列のような順序付けられた構造を使用することをお勧めします。

var db = [
  {key: 'a', value: 1},
  {key: 'b', value: 2},
  {key: 'c', value: 3}
];

その場合、next関数は次のようになります。

var next = function(db, key) {
  for (var i = 0; i < db.length; i++) {
    if (db[i].key === key) {
      return db[i + 1] && db[i + 1].value;
    }
  }
};

keyに存在しない場合、またはdb最後の場合は、をnext返しますundefined&&最後の項目の次を要求する予定がない場合は、三項演算子を削除して直接戻ることにより、その関数を簡略化できますdb[i + 1].value

Underscore.jsユーティリティメソッドのいくつかを使用して、次のことをnext簡単にすることもできます。

var next = function(db, key) {
  var i = _.pluck(db, 'key').indexOf(key);
  return i !== -1 && db[i + 1] && db[i + 1].value;
};

(この場合、時々next戻る可能性がfalseあります...しかしそれはまだ偽の値です:))


for inさて、より実用的な答えは、ほとんどのブラウザがオブジェクトを反復するときにオブジェクトが初期化された順序を尊重するため、他の答えが示唆するようにループでオブジェクトを反復できるということです。Object.keys配列を反復処理する作業を簡素化するために使用することをお勧めします。

// Assuming that db is an object as defined in the question.
var next = function(db, key) {
  var keys = Object.keys(db)
    , i = keys.indexOf(key);
  return i !== -1 && keys[i + 1] && db[keys[i + 1]];
};
于 2012-09-20T04:10:00.210 に答える
6
function next(db, key){   
  var found = 0; 
  for(var k in db){
    if(found){ return db[k]; }
    if(k == key){ found = 1; }
  }
}
于 2012-09-20T03:24:24.770 に答える
5

これに対する直接の解決策は、データを配列に格納し、オブジェクトを使用して、オブジェクトが存在する配列にインデックスを格納することです。

var db = {
    data: [1, 2, 3],
    index: {
        a: 0,
        b: 1,
        c: 2
    }
};
function next(db, key) {
    var next = db.index[key] + 1;
    if (next >= db.data.length) {
        return null;
    }
    return db.data[next];
}
function prev(db, key) {
    var next = db.index[key] - 1;
    if (next < 0) {
        return null;
    }
    return db.data[next];
}
function add(db, key, value) {
    db.index[key] = db.data.push(value) - 1;
}
function remove(db, key) {
    var index = db.index[key], x, temp;
    if (index !== undefined) {
        delete db.index[key];
        db.data.splice(index, 1);
        // Update indices of any elements after the removed element
        for (x in db.index) {
            temp = db.index[x];
            if (temp > index) {
                db.index[x] = temp - 1;
            }
        }
    }
}

基本的な考え方は、順序付けられた構造(この場合は配列)を使用して、データを順番に保持することです。この場合、nextとprevは両方とも一定時間であり、addは一定時間で償却され、deleteはO(N)です。

キーの順序はECMA標準によって保証されてfor/inいないため、キーが追加された順序である必要はありません(実際には、これが一般的な実装になる傾向があります)。このソリューションでは、配列を使用して挿入順序を明示的に追跡します。

編集:私は以前にスプライスで削除の問題を見落としていました。削除のスプライスされた値の後、インデックスはすべての値で正しくなくなります。この修正は、操作の実行時間の複雑さに影響を与えません。削除が少ない高速バージョンでは、配列がスパースになり、スプライシングの代わりに、インデックスをnullに設定するだけで、そこに格納されている参照を解放できます。これにより、削除操作がO(1)に下がります。

function remove(db, key) {
    var index = db.index[key];
    if (index !== undefined) {
        delete db.index[key];
        db.data[index] = null;
    }
}
于 2012-09-20T03:19:17.857 に答える
3

undercore.jsを使用すると、オブジェクトのキーを取得してトリックを実行できます。しかし、キーと値のペアが最初から何らかの方法で順序付けられているかどうかはわかりません。

var next = function(db, key) {
    var keys = _.keys(db);
    var index = _.indexOf(keys, key);
    if(index+1<keys.length){
         return db[keys[index+1]];
    }else{
        return null;
    }
}

jsFiddle: http: //jsfiddle.net/QWhN2/

于 2012-09-20T03:18:20.160 に答える
0

私は2021年にここに着陸したので、Es6ソリューションを投稿します。

開始キーを指定してオブジェクトをナビゲートできるようにする簡単なソリューション:

const navObj = (obj, currentKey, direction) => {
    return Object.values(obj)[Object.keys(obj).indexOf(currentKey) + direction];
};

const db = {
  a: 1,
  b: 2,
  c: 3
};

console.log(navObj(db, 'a', 1));
console.log(navObj(db, 'a', 2));
console.log(navObj(db, 'b', -1));

于 2021-01-14T17:22:42.560 に答える