【问题标题】:JSON and reference [duplicate]JSON和参考[重复]
【发布时间】:2015-07-09 05:44:34
【问题描述】:

我以 JSON 对象的形式接收数据,如下所示:

[{"transid":1091, "payee":"McDonalds", "amount":-549},
 {"transid":1092, "payee":"McDonalds", "amount":-342},
 {"transid":1093, "payee":"McDonalds", "amount":371}]

我知道我可以像这样访问数据:

alert(obj[0].amount);

但我希望能够像这样访问数据:

obj[transid].amount

其中transid 是先前声明和分配的变量,如下所示:

var transid = 1091;
alert(obj[transid].amount);  //returns -549

如果这是可能的,我认为 JSON 对象必须进行重组(我无法控制如何接收 JSON 对象),但我真的不知道如何去做.我已经尝试过 Google 搜索和 SOing,但我只是不确定要查找什么。

编辑:我已经按照 Travis J 的建议查看了建议的重复问题,但我不同意这是重复的。我不是要遍历数据。我要求通过特定索引引用的方法,因为我无法控制它对我的影响。提议的副本中接受的答案显示了我对代码外观的设想(在第二个代码框中),但我认为它并不能真正回答我的问题。 Hakan Bilgin 发布的建议副本中的另一个答案建议使用 defiantjs,这可能会起作用。但是,还有许多其他方法,其中一些已作为此问题的答案提供。

【问题讨论】:

  • 这个问题不完全是关于简单地在 JavaScript 对象中查找内容,而是关于这样做的语法。有一些相当有趣的方法可以让事情像 OP 建议的那样工作,包括一些预处理以及对象代理之类的东西,这些东西没有被假定的副本解决。应该重新打开。
  • Travis J 对重复问题的回答(目前是第 2 个,未接受)有一种蛮力搜索方法。它看起来做得很好,但提问者有兴趣获取按索引排序的数据。重复问题的最佳答案涵盖了如何处理索引数据,而不是如何转换。 This question 有一些代码作为起点,但无论如何都不是完全重复的。投票重新开放。
  • @bruno 和 ekuusela:感谢您的回复。我希望我可以将两者都标记为已接受的答案!与 .forEach 方法相比,我更喜欢 .filter 方法,但到目前为止,这只是因为我还不知道这两种解决方案的开销。假设我有 100000 个元素。哪个对时间的影响更小?重组 100000 个元素,然后按照 ekuusela 直接访问数据,还是按照 bruno 过滤数据?回家后我会进行测试,但我很欣赏这两个答案。我稍后会接受。

标签: javascript json


【解决方案1】:

您可以从该对象创建一个新对象。像这样的

var transactionArray = [
  {"transid":1091, "payee":"McDonalds", "amount":-549},
  {"transid":1092, "payee":"McDonalds", "amount":-342},
  {"transid":1093, "payee":"McDonalds", "amount":371}
];

var transactionsById = {};
transactionArray.forEach(function(element) {
    transactionsById[element.transid] = element;
});

var transid = 1091;
alert(transactionsById[transid].amount); //returns -549

transactionArray 是您在问题中所指的 obj

【讨论】:

  • 这是提问者需要的,但不在重复问题中。 +1
  • 感谢您的帮助。我玩过你和布鲁诺的答案。你的确实为我提供了我所寻求的句法解决方案。但是,我喜欢Array.prototype 解决方案(我最终使用.find 而不是.filter)。所以我将不得不更多地感受它......我选择哪个蛋糕?巧克力洒巧克力,还是三重巧克力不洒?
【解决方案2】:

你可以用filter点赞

obj.filter(function(o){
    return o['transid'] === 1091;
})[0].amount // -549

您可以将上述函数添加到Array的原型中

Array.prototype.get = function(id){
    return Array.prototype.filter.call(this,function(obj){
        return obj['transid'] === id;
    })[0].amount
}

并像使用它

obj.get(1091); // -549

您可以添加适当的验证,例如处理未找到的键和重复项。

【讨论】:

  • 如所写,如果调用者请求一个不在集合中的 transid,则会引发异常。否则,这是最简单的方法。
  • filter 即使在找到正确的对象后也会继续迭代。您可能想改用some,以便打破循环。
  • @bruno,感谢您的回复。我遵循 ekuusela 上面关于.some 的评论的引导。我的阅读理解是.some 返回真/假,我认为这不适用于您的答案。但是,使用.find polyfill,我认为它可以按预期工作。谢谢!
  • 对于some,您必须将找到的值分配给其他变量并使用它而不是some 的返回值。如果你有 polyfill,使用 find 会更好。 var result; a.some(function(e) { if (e.id === id) { result = e; return true; }});
猜你喜欢
  • 2012-07-24
  • 1970-01-01
  • 1970-01-01
  • 2016-06-25
  • 1970-01-01
  • 2011-01-21
  • 2015-08-06
  • 2013-06-22
  • 1970-01-01
相关资源
最近更新 更多