json 获取对象中的下一个键值对

ttvkxqim  于 5个月前  发布在  其他
关注(0)|答案(6)|浏览(50)

给定一个键,我想在一个对象中找到下一个属性。我不能依赖于键是有序的或顺序的(它们是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编写的解决方案:)

xhv8bpkk

xhv8bpkk1#

es6版本。我只是从storeObject中获取键,查找下一个Index。

const keys = Object.keys(storeObject);
 const nextItem = keys.at(keys.indexOf(theCurrentItem) +1);

字符串

jecbmhm3

jecbmhm32#

正确答案是:你不能这样做,因为objects are unordered as per ECMAScript's spec
我建议你使用一个有序的结构,比如数组,来解决这个问题:

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;
    }
  }
};


如果db上不存在key,或者它是最后一个,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;
};


(in在这种情况下,next有时会返回false...但它仍然是一个falsy值:))
现在,一个更实用的答案可能是,因为大多数浏览器在迭代对象时都会考虑对象的初始化顺序,所以你可以像其他答案建议的那样使用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]];
};

jljoyd4f

jljoyd4f3#

function next(db, key){   
  var found = 0; 
  for(var k in db){
    if(found){ return db[k]; }
    if(k == key){ found = 1; }
  }
}

字符串

4si2a6ki

4si2a6ki4#

一个直接的解决方案是将数据存储在数组中,并使用对象来简单地存储对象所在数组中的索引。

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不需要按照键被添加的顺序(尽管在实践中,这往往是常见的实现)。在这个解决方案中,我使用一个数组来显式地跟踪插入顺序。
编辑:我之前忽略了splice的一个删除问题。对于移除的拼接值之后的所有值,索引都将变得不正确。修复不会影响操作的运行时间复杂度。更快的版本,更少的移除可以让数组变得稀疏,而不是拼接,只需将索引设置为null以释放存储在那里的任何引用。这将使移除操作降低到O(1)。

function remove(db, key) {
    var index = db.index[key];
    if (index !== undefined) {
        delete db.index[key];
        db.data[index] = null;
    }
}

nhaq1z21

nhaq1z215#

使用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/

tsm1rwdh

tsm1rwdh6#

我在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));

字符串

相关问题