7

Here is my array:

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

From the above, I would like to get a array like this:

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

The array contains all the property names of the objects in the array of objects. I tried Form array of property names found in a JavaScript Object but the result was:

['0', '1']
Community
  • 1
  • 1
Aecio Levy
  • 149
  • 1
  • 8

8 Answers8

6

You could iterate the array with Array#forEach and get the keys with Object.keys and collect the names in an object. Then take the keys as result.

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);

ES6 with Set and spread syntax ...

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);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • That is even quicker as it won't need to call tons of `indexOf`. – ibrahim mahrir Jan 28 '17 at 16:18
  • @ibrahim mahrir I don't think this is any quicker than using `indexOf` – Redu Jan 28 '17 at 17:03
  • @Redu Why? I think objects use hashing so it would be quicker (in performance) than calling `indexOf` for each key of each object. – ibrahim mahrir Jan 28 '17 at 17:05
  • @Redu you said it yourself in your answer bellow. lol. (_is as quick as it could get_) – ibrahim mahrir Jan 28 '17 at 17:07
  • @ibrahim mahrir You are preventing the dupes with `indexOf` and Nina Scholz is doing the same job with a Set object. Do you think Set object eliminates dupes magically in O(1) time..? Both codes should be similar in terms of performance. – Redu Jan 28 '17 at 17:21
  • @Redu `Set` probably uses either a trie or hash structure, which has O(log n) or O(1) lookup times, respectively. – 4castle Jan 28 '17 at 17:36
  • @Redu I believe the hash is faster than `indexOf`. See [this answer](http://stackoverflow.com/questions/32234733/javascript-what-lookup-is-faster-array-indexof-vs-object-hash) and [this website](https://jsperf.com/array-indexof-vs-object-hash-lookup). – ibrahim mahrir Jan 28 '17 at 17:36
  • @ibrahim mahrir So yes I guess i have to apologize from Nina. Despite my initial thoughts her code turns out to be not so bad at all. It's simply faster than mine and 4castle's. However as i have said `indexOf` is not something you should simply disregard. My [test](https://repl.it/FYXN/2) shows ibrahim's code is even faster than Nina's. :) – Redu Jan 28 '17 at 21:03
3

You can very simply do as follows; I think it's probably the most efficient code so far.

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);
Redu
  • 25,060
  • 6
  • 56
  • 76
  • `Object.assign` is ES6, then you could use 4castle's idea with spreaded objects. – Nina Scholz Jan 28 '17 at 17:07
  • @Nina Scholz Oh.. I hadn't seen that comment. (even i had searched for the assign keyword in the page) That's also a pretty valid idea of course but the spread operator "might" turn out to be slow. Let me up-vote his comment. – Redu Jan 28 '17 at 17:13
  • It's more likely the spread operator would be faster. There's much fewer function calls. – 4castle Jan 28 '17 at 17:18
  • @4castle You might be right with the function calls. I wish i could make `.reduce(Object.assign)` alas `i` and `a` (the index and the array itself) jumps into the mix. – Redu Jan 28 '17 at 17:26
  • @4castle I was curious.. So i did some [tests](https://repl.it/FYXN). It seems your code has two problems. 1) As i was suspecting it's slow due to the spread operator. 2) Whats more to the point, the spread operator has one other major disadvantage.. You can not feed it with an array of indefinitely many items.. In this particular case it turns out to be for above 500K items, you will get a RangeError: Maximum call stack size exceeded... So there is also that. – Redu Jan 28 '17 at 20:43
  • @Redu I [modified the tests](https://repl.it/FYXN/3) some so that there is less randomness in the comparison, and the spread syntax is typically 10-30 ms slower. For data of that size, the performance difference in negligible. I agree the call stack limit is the main difference. – 4castle Jan 28 '17 at 21:23
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);
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
0

You could try something like this:

 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);
Christos
  • 53,228
  • 8
  • 76
  • 108
0

Ecmascript5 solution using Array.prototyp.reduce() and Object.keys() functions:

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);

Ecmascript6 solution using Set objects and Array.from function:

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] within new Set([...r, ...newSet]) means that r and newSet are converted to arrays and concatenated.

RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
0

First get all the properties from the array using Object.keys and then filter out to get the distinct ones

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);
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
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));

So collectProperties(testeArray) returns ['name', 'esteira', 'horse'].

Or in 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))
yivo
  • 3,324
  • 1
  • 18
  • 23
0

With ES6 you can use Set and spread syntax ... to do this.

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)
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176