导航到 Javascript 对象中的上一项和下一项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15185199/
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
Navigating to previous and next item in a Javascript object
提问by Starx
I want to navigate up and down an JavaScript Object given an item of an object. An example object:
我想在给定对象的项目的情况下在 JavaScript 对象上上下导航。一个示例对象:
var items = {
"5" : ["name", "link2"],
"8" : ["name 2", "link 2"],
"11" : ["name 3", "link 3"]
}
Now, given I have the item items["8"]
. I want to get previous and next item respectively.
现在,鉴于我有项目items["8"]
。我想分别获得上一个和下一个项目。
getItemBefore = function(index) {
// index holds 8
// should return "5"
}
getItemAfter = function(index) {
// index hold 8
// should return 11
}
How can I get those items?
我怎样才能得到这些物品?
回答by lemonzi
The keys that an object holds can be retrieved as an array with Object.keys(<var>)
. The order of the keys in the array is arbitrary; you need to sort them before indexing. An option is the built-in sort()
method for arrays, which is especially useful because custom comparison functions can be provided (see below). Default order is alphabetical.
对象持有的键可以作为数组检索Object.keys(<var>)
。数组中键的顺序是任意的;您需要在索引之前对它们进行排序。一个选项是sort()
数组的内置方法,它特别有用,因为可以提供自定义比较函数(见下文)。默认顺序是按字母顺序排列。
Once you get the ordered array, you only need to look up where your item is in the array and return the next and previous elements from it:
获得有序数组后,您只需要查找您的项目在数组中的位置并从中返回下一个和上一个元素:
var keys = Object.keys(items).sort();
var loc = keys.indexOf(item);
Given that loc > -1
(that is, the item exists):
鉴于loc > -1
(即该项目存在):
- Previous item:
items[keys[loc-1]]
, but check thatloc > 0
(it's not the first one). - Next item:
items[keys[loc+1]]
, but check thatloc < keys.length
(it's not the last one).
- 上一项:
items[keys[loc-1]]
,但请检查loc > 0
(这不是第一个)。 - 下一项:
items[keys[loc+1]]
,但请检查loc < keys.length
(这不是最后一项)。
Object.keys
is compatible with Javascript 1.85+; hereis a workaround for older browsers.
Object.keys
与 Javascript 1.85+ 兼容;这是旧浏览器的解决方法。
Alternative orderings
替代顺序
Numerical
数字
If you want the keys to have a numerical order, use this comparison function:
如果您希望键具有数字顺序,请使用此比较函数:
var keys = Object.keys(items).sort( function(a,b) {
return b - a;
});
Creation (or Modification) Time
创建(或修改)时间
If you want to work with creation order instead of alphanumeric, the items must hold their creation time. Something like:
如果您想使用创建顺序而不是字母数字,则项目必须保持其创建时间。就像是:
<value>.index = Date.getTime();
items['<item>'] = <value>;
Then, the sort()
method needs the following comparison function:
然后,该sort()
方法需要以下比较函数:
var keys = Object.keys(items).sort( function(a,b) {
return b.index - a.index;
});
This can be easily extended to last modification ordering or similar.
这可以很容易地扩展到最后修改顺序或类似的。
Creation Order
创建顺序
Notice that the former solution only works if the items are created more than 1 ms apart, which would be suitable for user actions. If the items are added faster, use this instead of the timestamp:
请注意,前一种解决方案仅在创建的项目相隔 1 毫秒以上时才有效,这适用于用户操作。如果项目添加得更快,请使用它而不是时间戳:
<value>.index = Object.keys(items).length;
Or, alternatively, keep an external counter with the number of items in the object.
或者,保留一个带有对象中项目数的外部计数器。
回答by myfunkyside
This answer builds upon @lemonzi's answer, see his answerfor more detailed explanations.
这个答案建立在@lemonzi的答案之上,请参阅他的答案以获取更详细的解释。
I just wanted to add a working example for everyone struggling with this:
我只是想为每个为此苦苦挣扎的人添加一个工作示例:
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));
- This way you only need one function to change item.
- The
.sort(function(a,b){return a-b;})
sorts the array numerical. - The
if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {
checks that the item is not the first or the last index in the array, and if it is, it returns the index itself.
- 这样你只需要一个功能来改变项目。
- 所述
.sort(function(a,b){return a-b;})
排序阵列数值。 - 所述
if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {
检查该项目不是阵列中的第一个或最后一个索引,并且如果它是,则返回索引本身。
If you want to display a message if the item is the first or the last, use this instead:
如果要在项目是第一个或最后一个时显示消息,请改用:
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));
- The
(i==1?"last":"first")
is called a ternary operator, read about it.
- 在
(i==1?"last":"first")
被称为三元运算符,了解它。
回答by lmortenson
This is a bit tricky, because technically according to the ECMAScript specifications, the order of properties in an object is implementation specific. That means there's no guarantee in the language that your properties will be in the same order each time you access them. If you're relying on that, there's a potential there could be a problem.
这有点棘手,因为从技术上讲,根据 ECMAScript 规范,对象中属性的顺序是特定于实现的。这意味着在语言中无法保证每次访问时您的属性都处于相同的顺序。如果您依赖它,则可能会出现问题。
See this bug in Chrome. It states that Chrome doesn't promise to return your keys in any particular order, and it's been marked "WONTFIX" for 4-5 years now. That means that you can't rely on that behavior in Chrome, and here's another postindicating that now IE9 has the same "issue".
在 Chrome 中查看此错误。它声明 Chrome 不承诺以任何特定顺序返回您的密钥,并且它已被标记为“WONTFIX” 4-5 年了。这意味着您不能依赖 Chrome 中的这种行为,这是另一篇文章,表明现在 IE9 具有相同的“问题”。
So, I would recommend that you create your own object to manage your keys, and use a JavaScript object behind the scenes to store your keys.
因此,我建议您创建自己的对象来管理您的密钥,并在幕后使用 JavaScript 对象来存储您的密钥。
Here's something I threw together, it doesn't support deletes and it has no bounds checking, but it should serve your purposes. Fiddle here.
这是我拼凑的东西,它不支持删除,也没有边界检查,但它应该符合您的目的。在这里摆弄。
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"))
回答by adamS
Would an array of objects be more appropriate here? The example below could be wrapped in an object and making the nextItem() and prevItem() methods. With this you might also need some bounds checking.
对象数组在这里更合适吗?下面的示例可以包装在一个对象中并创建 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'));