通过键值在对象数组中查找元素

3

什么是在对象数组中通过键的值查找元素(对象)的最佳结构解决方案。

例如,我们有以下数组:

var someArray = 
[  {id:17, color:'black', width:50},  {id:34, color:'red', width:150},  {id:49, color:'gree', width:10}]

我们需要找到一个id-key为34的对象。

每次我们都必须循环查找对象。 我考虑重新构造,将数组改为对象形式,如下所示:

 var someObject = 
    {
      17: {id:17, color:'black', width:50},
      34: {id:34, color:'red', width:150},
      49: {id:49, color:'gree', width:10}
    }

现在我们可以通过一步操作来获取某个对象的第34个元素,但如果我们想保持顺序呢?
提前感谢您的帮助。

“保持顺序”是什么意思?一个对象的属性之间没有“顺序”。当然,你可以使用Object.keysfor (... in ... )获取键,但据我所知,你不能依赖它的顺序,因为它可能会因浏览器而异。 - MaxArt
1
我之前做过的是创建了一个包含对象数组和字典的类。当我搜索需要的对象时,我保存对象的标识符和在字典中的行/索引。当我尝试在这个类中查找对象时,我首先查看字典 - 如果它有ID的记录,我检查它的索引是否指向相同的对象而不是不同的/空的/超出范围的。如果没有,那么我会搜索并将标识符/行保存在字典中。这种方法效果很好,而且易于实现。 - Andrew Mack
3个回答

2

我考虑重构,使用对象代替数组。

好的,没问题。

但是如果我们想保留顺序呢?

我倾向于使用一个额外的数组来按正确的顺序包含键,例如:

var order = [17, 34, 47];

要循环它们,您可以使用:

for (var i=0; i<order.length; i++) {
    … someObject[order[i]] …
}

1

您可以使用underscore库中的findWhere函数,对于您的情况,使用如下:

_.findWhere(someArray, {id: 34})

1

为避免命名冲突,您应该在id前加上前缀,如下所示:

var database = 
{
  'row_17' : {id:17, color:'black', width:50},
  'row_34' : {id:34, color:'red',   width:150},
  'row_49' : {id:49, color:'gree',  width:10}
};

此时,您可以使用以下代码查询对象:

function retrieve(database, id)
{
  id = 'row_' + id;

  if (!database.hasOwnProperty(id))
  {
    return null;
  }

  return database[id];
}

persist函数将会是:

function persist(database, obj)
{
  database['row_' + obj['id']] = obj;
}

如果您需要保持顺序,首先需要了解您所谈论的顺序是什么。

id的顺序吗?是插入的顺序吗?还是任意属性的顺序?

对于所有这些问题,都有解决方案,可以通过筛选(提取项目并将它们放入单独的数组中作为查询结果或使用附加字段或结构)来实现。

编辑:如何保持插入顺序

您需要一个跟踪顺序的数组:

database._ordered = [];

在插入时,也将项目推到那里:
database._ordered.push(obj);

现在你可以通过关键字和所有已排序的项目选择单个项目。 对象中没有办法保持顺序,它只是错误的工具。 建议使用“row_”前缀避免与方法等命名冲突。 对象应该包含属性和方法,如果您像使用字典一样使用它,至少要加前缀以避免干扰。

你并没有一个明确的订单,订单取决于你如何列出项目。如果你想保持插入顺序,你可以采用我的解决方案并轻松地进行调整。 - pid
抱歉,但我认为这不是一个解决方案。我已经描述了这种情况。你只是将其包装成函数并添加“row_”前缀(不知道为什么)。 - Stepan Suvorov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接