Javascript 获取对象中的下一个键值对
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12505598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get next key-value pair in an object
提问by captainclam
Given a key, I want to find the next property in an object. I can not rely on the keys to be ordered or sequential (they're uuids). Please see below for trivial example of what I want:
给定一个键,我想在一个对象中找到下一个属性。我不能依赖要排序或顺序的键(它们是 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
I also want a prev() function, but I'm sure it will be the same solution.
我也想要一个 prev() 函数,但我相信它会是相同的解决方案。
This seems like such a trivial problem but I can't for the life of me figure out how to do it.
这似乎是一个微不足道的问题,但我一生都无法弄清楚如何去做。
Happy for the solution to use underscore.js or be written in coffeescript :)
很高兴使用 underscore.js 或用 coffeescript 编写的解决方案:)
回答by epidemian
The correct answer is: you can't do that, as objects are unordered as per ECMAScript's spec.
正确答案是:你不能这样做,因为对象按照 ECMAScript 的规范是无序的。
I'd recommend that you use an ordered structure, like an array, for the purpose of the problem:
为了解决问题,我建议您使用有序结构,例如数组:
var db = [
{key: 'a', value: 1},
{key: 'b', value: 2},
{key: 'c', value: 3}
];
Then the next
function can be something like:
然后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;
}
}
};
In case key
does not exist on db
or it was the last one, next
returns undefined
. if you're never going to ask for the next of the last item, you can simplify that function by removing the ternary &&
operator and returning db[i + 1].value
directly.
如果key
不存在db
或它是最后一个,则next
返回undefined
。如果您永远不会要求最后一项中的下一项,则可以通过删除三元&&
运算符并db[i + 1].value
直接返回来简化该函数。
You can also use some of Underscore.js utility methods to make next
simpler:
您还可以使用一些 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 this case next
could return false
sometimes... but it's still a falsy value :))
(在这种情况下有时next
可能会返回false
......但它仍然是一个错误的值:))
Now, a more pragmatic answer could be that, as most browsers will respect the order in which an object was initialized when iterating it, you can just iterate it with a for in
loop as the other answers suggest. I'd recommend using Object.keys
to simplify the job of iterating over the array:
现在,更实用的答案可能是,由于大多数浏览器在迭代对象时会尊重对象的初始化顺序,因此您可以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]];
};
回答by httpete
ts / es6 version. I simply get the keys from the storeObject, look for the next Index.
ts/es6 版本。我只是从 storeObject 获取键,寻找下一个索引。
let keys = Object.keys(storeObject);
let nextIndex = keys.indexOf(theCurrentItem) +1;
let nextItem = keys[nextIndex];
回答by anson
function next(db, key){
var found = 0;
for(var k in db){
if(found){ return db[k]; }
if(k == key){ found = 1; }
}
}
回答by Justin Summerlin
An immediate solution to this would be to store data in an array and use the object to simply store the index in the array at which an object exists.
对此的直接解决方案是将数据存储在数组中,并使用对象来简单地存储对象所在数组中的索引。
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;
}
}
}
}
The basic idea is to use an ordered structure, in this case the array, to hold the data in a sequential manner. In this case, next and prev are both constant time, add is amortized constant time, and delete is O(N).
基本思想是使用有序结构(在本例中为数组)以顺序方式保存数据。在这种情况下,next 和 prev 都是常数时间,add 是摊销常数时间,delete 是 O(N)。
The ordering of keys isn't guaranteed by the ECMA standard, so for/in
doesn't need to be in the order keys were added (though in practice, that does tend to be the common implementation). In this solution, I use an array to explicitly keep track of insert order.
ECMA 标准不保证键的顺序,因此for/in
不需要按照键的添加顺序(尽管在实践中,这确实是常见的实现)。在这个解决方案中,我使用一个数组来明确跟踪插入顺序。
Edit: I overlooked a deletion issue earlier with splice. The index would become incorrect for all values after the spliced value for a remove. The fix doesn't impact the running time complexity of the operation. A faster version with fewer removes could let the array become sparse and instead of splicing, simply set the index to null to free any reference stored there. This would lower the remove operation to O(1).
编辑:我之前忽略了 splice 的删除问题。在删除拼接值之后,所有值的索引都将变得不正确。此修复不会影响操作的运行时间复杂度。删除更少的更快版本可以让数组变得稀疏,而不是拼接,只需将索引设置为 null 即可释放存储在那里的任何引用。这会将删除操作降低到 O(1)。
function remove(db, key) {
var index = db.index[key];
if (index !== undefined) {
delete db.index[key];
db.data[index] = null;
}
}
回答by janith
Using undercore.js, you can take the keys of an object and do the trick. But I'm not sure if the key-value pairs are ordered in any way to begin with:
使用 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/
jsFiddle:http: //jsfiddle.net/QWhN2/