如何获取数组中对象的属性名称?

7
这是我的数组:
var testeArray = [
    {name: "Jovem1", esteira: "Macaco"},
    {name: "Jovem", esteira: "Doido", horse: "Chimbinha"}
];

从上面的代码中,我想获得一个像这样的数组:

var propertyName = ["name", "esteira", "horse"];

该数组包含了数组对象中所有属性名称。我尝试过在JavaScript对象中形成属性名称的数组,但结果如下:

['0', '1']

2
这是因为您正在获取数组的属性,而不是其中的对象。 - Andrew Li
8个回答

6
你可以使用 Array#forEach 迭代数组,使用 Object.keys 获取键,并将名称收集到一个对象中。然后以键为结果。

var testeArray = [{name: "Jovem1", esteira: "Macaco"}, {name: "Jovem", esteira: "Doido", horse: "Chimbinha" }],
    names = Object.create(null),
    result;

testeArray.forEach(function (o) {
    Object.keys(o).forEach(function (k) {
        names[k] = true;
    });
});

result = Object.keys(names);
console.log(result);

使用Set...展开语法的ES6

var array = [{name: "Jovem1", esteira: "Macaco"}, {name: "Jovem", esteira: "Doido", horse: "Chimbinha" }],
    names = [...array.reduce((s, o) => (Object.keys(o).forEach(k => s.add(k)), s), new Set)];
console.log(names);


这甚至更快,因为它不需要调用大量的 indexOf - ibrahim mahrir
@ibrahim mahrir,我认为这并不比使用indexOf更快。 - Redu
@Redu,你在下面的回答中自己说了。哈哈。 (速度已快到极致) - ibrahim mahrir
@ibrahim mahrir,你正在使用indexOf来防止重复,而Nina Scholz则使用Set对象来完成同样的工作。你认为Set对象能够以O(1)的时间神奇地消除重复吗?两种代码在性能上应该是相似的。 - Redu
@Redu Set 可能使用 trie 或 hash 结构,分别具有 O(log n) 或 O(1) 的查找时间。 - 4castle
显示剩余3条评论

3
你可以非常简单地按照以下方式操作;我认为这可能是到目前为止最有效的代码。

var testArray = [
    {name: "Jovem1", esteira: "Macaco"},
    {name: "Jovem", esteira: "Doido", horse: "Chimbinha"}
],
props = Object.keys(testArray.reduce((o,c) => Object.assign(o,c)));
console.log(props);


Object.assign 是 ES6 中的方法,因此您可以使用 4castle 的想法来处理扩展对象。 - Nina Scholz
@Nina Scholz 哦..我没有看到那个评论。(即使我在页面上搜索了assign关键字) 当然,这也是一个非常有效的想法,但扩展运算符“可能”会变得很慢。让我点赞他的评论。 - Redu
扩展运算符更有可能更快。函数调用较少。 - 4castle
@4castle 你可能在函数调用方面是正确的。我希望我能够使用.reduce(Object.assign),但是ia(索引和数组本身)卷入了混乱中。 - Redu
@4castle 我很好奇,所以我做了一些测试。看起来你的代码有两个问题。1)正如我怀疑的那样,由于展开运算符,它很慢。2)更重要的是,展开运算符还有另一个主要缺点...你不能用无限多的项目数组来填充它。在这种特殊情况下,结果是超过500K个项目,你会得到一个RangeError:Maximum call stack size exceeded...所以也有这个问题。 - Redu
@Redu 我修改了一些测试,使比较过程中的随机性降低了,而且展开语法通常会慢10-30毫秒。对于那种规模的数据,性能差异可以忽略不计。我同意调用堆栈限制是主要区别。 - 4castle

1

var testArray = [{
  name: "Jovem1",
  esteira: "Macaco"
}, {
  name: "Jovem",
  esteira: "Doido",
  horse: "Chimbinha"
}];

var propName = [];

testArray.forEach(function(o) {
  Object.keys(o).forEach(function(prop) {
    if (propName.indexOf(prop) < 0)
      propName.push(prop);
  });
});

console.log(propName);


0
你可以尝试这样做:

 var testeArray = [
    {name: "Jovem1", esteira: "Macaco"},
    {name: "Jovem", esteira: "Doido", horse: "Chimbinha" }
  ];

// The array in which we push the unique property names.
var properties = [];

testeArray.forEach(function(obj){
    for(var key in obj){
       if(obj.hasOwnProperty(key) 
          && properties.indexOf(key) === -1) { 
          // It's the first time we hit key. So push it to the array.
         properties.push(key);
       }
    }
});

console.log(properties);


0

Ecmascript5解决方案使用Array.prototyp.reduce()Object.keys()函数:

var testeArray = [
    {name: "Jovem1", esteira: "Macaco"},
    {name: "Jovem", esteira: "Doido", horse: "Chimbinha" }
  ],
    keys = testeArray.reduce(function(r, o) {
        Object.keys(o).forEach(function (k) {
            if (r.indexOf(k) === -1) r.push(k);
        })
        return r;
    }, []);

console.log(keys);


ECMAScript 6解决方案使用Set对象和Array.from函数:

var testeArray = [
    {name: "Jovem1", esteira: "Macaco"},
    {name: "Jovem", esteira: "Doido", horse: "Chimbinha" }
  ],
    keys = testeArray.reduce(function(r, o) {
        var newSet = new Set(Object.keys(o));
        return new Set([...r, ...newSet]);
    }, new Set());

console.log(Array.from(keys));

[...r, ...newSet]new Set([...r, ...newSet]) 中的意思是将 rnewSet 转换为数组并进行连接。


0

首先使用Object.keys从数组中获取所有属性,然后进行筛选以获取不同的属性

var testeArray = [
    {name: "Jovem1", esteira: "Macaco"},
    {name: "Jovem", esteira: "Doido", horse: "Chimbinha" }
  ]

var properties = [];
testeArray.forEach(function (o) {
    Object.keys(o).forEach(function (k) {
        properties.push(k)
    });
});

var distProps = properties.filter(function(item, i, arr) {
    return arr.indexOf(item) === i;
})
console.log(distProps);


0

使用ES6,您可以使用Set和展开语法...来实现此目的。

var testeArray = [
  {name: "Jovem1", esteira: "Macaco"},
  {name: "Jovem", esteira: "Doido", horse: "Chimbinha" }
];

var result = [...new Set([].concat(...testeArray.map(e => Object.keys(e))))]
console.log(result)


0

function collectProperties(arrayOfObjects) {
  return arrayOfObjects.reduce(function(memo, object) {
    Object.keys(object).forEach(function(key) {
      if (memo.indexOf(key) === -1) { memo.push(key) };
    });
    return memo;
  }, []);
}

var testArray = [
  {name: "Jovem1", esteira: "Macaco"},
  {name: "Jovem", esteira: "Doido", horse: "Chimbinha"}
];

console.log(collectProperties(testArray));

所以collectProperties(testeArray)返回['name', 'esteira', 'horse']

或者在CoffeeScript中:

collectProperties = (arrayOfObjects) ->
  properties = []
  for object in arrayOfObjects
    for own property of object when property not in properties
      properties.push(property)
  properties

testArray = [
  {name: "Jovem1", esteira: "Macaco"}
  {name: "Jovem", esteira: "Doido", horse: "Chimbinha"}
]

console.log(collectProperties(testArray))

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