导航到Javascript对象中的上一个和下一个项目

时间:2013-03-03 11:32:18

标签: javascript javascript-objects

我想在给定对象项目的情况下向上和向下导航JavaScript对象。示例对象:

var items = {
   "5" : ["name", "link2"],
   "8" : ["name 2", "link 2"],
   "11" : ["name 3", "link 3"]
}

现在,鉴于我有items["8"]项。我想分别得到上一个和下一个项目。

getItemBefore = function(index) {
    // index holds 8
    // should return "5"
}

getItemAfter = function(index) {
    // index hold 8
    // should return 11
}

我如何获得这些物品?

4 个答案:

答案 0 :(得分:12)

对象所持有的键可以作为具有Object.keys(<var>)的数组进行检索。数组中键的顺序是任意的;你需要在索引之前对它们进行排序。一个选项是数组的内置sort()方法,这是特别有用的,因为可以提供自定义比较函数(见下文)。默认顺序是按字母顺序排列的。

获得有序数组后,您只需要查找项目在数组中的位置并返回其中的下一个和前一个元素:

var keys = Object.keys(items).sort();
var loc = keys.indexOf(item);

鉴于loc > -1(即项目存在):

  • 上一项:items[keys[loc-1]],但请检查loc > 0(这不是第一个)。
  • 下一项:items[keys[loc+1]],但请检查loc < keys.length(这不是最后一项)。

Object.keys与Javascript 1.85+兼容; here是旧版浏览器的解决方法。

替代订单

数值

如果您希望键具有数字顺序,请使用此比较功能:

var keys = Object.keys(items).sort( function(a,b) {
    return b - a;
});

创建(或修改)时间

如果您想使用创建顺序而不是字母数字,则项目必须保留其创建时间。类似的东西:

<value>.index = Date.getTime();
items['<item>'] = <value>;

然后,sort()方法需要以下比较函数:

var keys = Object.keys(items).sort( function(a,b) {
    return b.index - a.index;
});

这可以很容易地扩展到最后的修改顺序或类似。

创建订单

请注意,前一个解决方案仅在项目间隔时间超过1毫秒时才有效,这适用于用户操作。如果项目添加得更快,请使用此项而不是时间戳:

<value>.index = Object.keys(items).length;

或者,也可以使用对象中的项目数保留外部计数器。

答案 1 :(得分:3)

此答案建立在@lemonzi的答案之上,有关详细说明,请参阅his answer

我只是想为每个苦苦挣扎的人添加一个有效的例子:

&#13;
&#13;
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));
&#13;
&#13;
&#13; jsfiddle:https://jsfiddle.net/p09yL01f/3/

  • 这样您只需要一个功能来更改项目。
  • .sort(function(a,b){return a-b;}) sorts the array numerical
  • if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {检查项目不是数组中的第一个或最后一个索引,如果是,则返回索引本身。

如果要在项目是第一项或最后一项时显示消息,请改为使用此项:

if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {return items[keys[index+i]];}
else {return (i==1?"last":"first")+" item";}

&#13;
&#13;
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));
&#13;
&#13;
&#13; jsfiddle:https://jsfiddle.net/p09yL01f/4/

答案 2 :(得分:2)

这有点棘手,因为从技术上讲,根据ECMAScript规范,对象中属性的顺序是特定于实现的。这意味着无法保证语言中每次访问时您的属性都处于相同的顺序。如果你依赖它,那么可能存在问题。

bug in Chrome。它声明Chrome不承诺以任何特定顺序返回您的密钥,并且它已被标记为“WONTFIX”已有4 - 5年了。这意味着您无法依赖Chrome中的这种行为,而another post表示现在IE9具有相同的“问题”。

因此,我建议您创建自己的对象来管理密钥,并在后台使用JavaScript对象来存储密钥。

这是我扔在一起的东西,它不支持删除,它没有边界检查,但它应该服务于你的目的。 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"))

答案 3 :(得分:0)

这里的一系列对象会更合适吗?下面的示例可以包装在一个对象中,并生成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'));