给定一个键,我想找到对象中的下一个属性。我不能依赖键来排序或顺序(它们是 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编写的解决方案:)
es6版本。我只是从 storeObject 获取键,查找下一个索引。
let keys = Object.keys(storeObject);
let nextItem = keys.at(keys.indexOf(theCurrentItem) +1);
正确的答案是:你不能这样做,因为根据 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]];
};
function next(db, key){
var found = 0;
for(var k in db){
if(found){ return db[k]; }
if(k == key){ found = 1; }
}
}
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;
}
}
一个简单的解决方案,让您可以在给定启动键的情况下导航对象:
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));