【问题标题】:How can I replicate Python's dict.items() in Javascript?如何在 Javascript 中复制 Python 的 dict.items()?
【发布时间】:2011-07-17 08:35:01
【问题描述】:

在 Javascript 中,我有一个 JSON 对象,我只想处理其中的项目:

var json = {
    itema: {stuff: 'stuff'},
    itemb: {stuff: 'stuff'},
    itemc: {stuff: 'stuff'},
    itemd: {stuff: 'stuff'}
}

在 Python 中我可以做到

print json.items()
[{stuff: 'stuff'},{stuff: 'stuff'},{stuff: 'stuff'},{stuff: 'stuff'}]

这个是js可以吗?

【问题讨论】:

  • 我可能应该补充一点,我想要这样做的 原因 以便我可以对数组进行排序(键只是 uid),所以也许我应该问“如何对关联数组中的项目进行排序”。
  • 问题不正确。 Python 的 dict.items() 返回 (key,value) 元组的列表。您的 retval 示例对应于dict.values()

标签: javascript associative-array


【解决方案1】:

在不扩展 Object.prototype 的情况下,你不能像在 python 中那样做这件事,你不想这样做,因为它是通往痛苦的道路。

您可以轻松地创建一个辅助函数,该函数可以遍历对象并将值放入数组中,如下所示:

function items(obj) {
 var i, arr = [];
 for(i in obj) {
   arr.push(obj[i]);
 }
 return arr;
}

Ps:JSON 是一种数据格式,你拥有的是一个对象字面量。

【讨论】:

  • 关于对象字面量的观点,它们在 js 中的联系非常紧密,你可能会原谅我。
【解决方案2】:

在 python 中,dict.items 返回一个包含 dict 的键和值的元组列表。 Javascript 没有元组,所以它必须是一个嵌套数组。

请原谅我用一点 Python 代码来说明区别。

>>> {1:2, 2:3}.items()
[(1, 2), (2, 3)]
>>> {1:2, 2:3}.values()
[2, 3]

我看到接受的答案返回一个对象值数组,这相当于 python 函数dict.values。要求的是dict.items。为此,只需循环并构建一个包含 2 个元素数组的嵌套数组。

function items(obj){

    var ret = [];
    for(v in obj){
        ret.push(Object.freeze([v, obj[v]]));
    }
    return Object.freeze(ret);
}

我把Object.freeze 放得很迂腐,并强制不应该更改返回值,以模拟python 元组的不变性。显然,如果你把它拿出来,它仍然有效。

应该注意的是,这样做在某种程度上违背了items 的目的,因为它在以线性而不是关联方式迭代对象时使用,并且它避免计算哈希值以查找关联中的每个元素大批。对于关心的小对象,但对于大对象,它可能会减慢您的速度,并且可能有一种更惯用的方式在 javascript 中执行您想要的操作。

另一种较新的方法是使用Object.entries(),这将完全满足您的需求。

Object.entries({1:1, 2:2, 3:3})
      .forEach(function(v){
          console.log(v)
      });

支持仅限于文档中提到的浏览器版本。

【讨论】:

  • 你应该放弃.hasOwnProperty() 电话。没有优势。
  • 不,只是那里毫无意义。有什么好的条件?您要枚举的常用对象不会具有继承的可枚举属性。如果你想防御那些拥有的,你肯定想防御那些拥有.hasOwnProperty 属性的人。
  • 哦,好的,谢谢。我虽然它会从父类中排除任何属性。我是 javascript 的相对菜鸟,所以不太了解。
  • s'pose 这些东西只是Object 的权利,所以不会有任何值得排除的东西。
【解决方案3】:

感谢最近对 JavaScript 的更新 - 我们现在可以解决这个问题:

function items(iterable) {
    return {
        [Symbol.iterator]: function* () {
            for (key in iterable) {
                yield [key, iterable[key]];
            }
        }
    };
}

for (const [key, val] of items({"a": 3, "b": 4, "c": 5})) {
    console.log(key, val);
}
// a 3
// b 4
// c 5

for (const [key, val] of items(["a", "b", "c"])) {
    console.log(key, val);
}
// 0 a
// 1 b
// 2 c

【讨论】:

  • 这相当于python中的enumerate,而不是OP要求的
  • 在 JS 中,数组是一个类似列表的对象,其中键是索引。为了避免混淆,我添加了一个带有对象的 items 函数示例。 @IuliusCurt 仅供参考
【解决方案4】:

ubershmekel 的答案使用惰性评估,而我下面的答案使用急切评估。惰性评估有很多好处,这使得它在某些情况下更适合性能原因,但急切评估的透明性可能是开发速度的好处,在其他情况下可能会使其更受欢迎。

const keys = Object.keys;

const values = object =>
  keys(object).map(key => object[key]);

const items = object =>
  keys(object).map(key => [key, object[key]])


obj = {a: 10, b: 20, c: 30};

keys(obj)   // ["a", "b", "c"]
values(obj) // [10, 20, 30]
items(obj)  // [["a", 10], ["b", 20], ["c", 30]]

items(obj).forEach(([k, v]) => console.log(k, v))
// a 10
// b 20
// c 30

【讨论】:

    【解决方案5】:

    不确定你想做什么,但我猜 Json.stringify 会做类似的事情。见http://www.json.org/js.html

    【讨论】:

      猜你喜欢
      • 2019-06-13
      • 2013-07-25
      • 2019-09-30
      • 2018-01-04
      • 2019-12-22
      • 2021-06-01
      • 1970-01-01
      • 2014-05-30
      • 2017-11-17
      相关资源
      最近更新 更多