How to convert an object into an array? - javascript

I have array of object and I want to change into array an remove object.
My object is like:
[{ABC: "ELEMENT1", MAX: 2, MIN: "Yes"}, {ABC: "ELEMENT2", MAX: 1, MIN: "Yes"}]
and I want result like array with index:
[{"ELEMENT1",2,"Yes"},{"ELEMENT2",2,"Yes}]

Use Array#map over Object.keys(obj)
The Object.keys() method returns an array of a given object's own enumerable properties.
The map() method creates a new array with the results of calling a provided function on every element in this array.
var ip = {
STU: "Study1",
SUB: 2,
EXL: "Yes"
};
var op = Object.keys(ip).map(function(key) {
return ip[key];
});
console.log(op);
To iterate Array-of-Objects
var ip = [{
STU: "Study1",
SUB: 2,
EXL: "Yes"
}, {
STU: "Study2",
SUB: 4,
EXL: "No"
}];
var op = ip.map(function(item) {
return Object.keys(item).map(function(key) {
return item[key];
});
});
console.log(op);

That would be:
var array = Object.keys(obj).map(key => obj[key]);
However, order is not guaranteed for Object.keys as it works like a for-in loop, whose order of traversal is arbitrary. You may not get ["Study1",2,"Yes"] in that exact order. If you want to guarantee order, you must use an array containing the order of the keys and extract them from your object in that order.
var keyArray = ['STU', 'SUB', 'EXL'];
var array = keyArray.map(key => obj[key]);

Related

From an array of objects, extract properties into multiple arrays (one per property)?

I have a JSON array of objects in JS that look something like this:
"data": [
{"name": "abc", "location": "NY", "value": 1234, "potato": "tomato", "someOtherProp": "prop1"},
{"name": "def", "location": "CA", ... etc}
{etc ...},
]
I'm creating a UI for filtering down some of these fields and want to create an array for each attribute with all the given values in the data.
I know this is possible using something like this:
let result = objArray.map(a => a.name);
But using this strategy, I have to run map once for every property. Is there any way to only go through the array once but create a separate array for each? (Or is there a better way in general for creating filter options for a UI?)
To clarify, for the array above, I'd want an array for "names" (containing "abc" and "def"), an array for "locations" (containing NY, CA, etc.) an array for "potato"s and "someOtherProp".
I appreciate any help!
Thanks
Loop through the array with .reduce(). In each iteration, loop through the keys of the object using Object.keys(), adding any unique values to an array of the same name.
This solution eliminates duplicate entries and works with any amount of properties.
const data = [{name: "abc", location: "NY"},{name: "def", location: "CA"},{name: "xyz", location: "TX"},{name: "zyx", location: "TX"}];
const getFiltersFromData = (data) => {
return data.reduce((out,obj) => {
Object.keys(obj).forEach(k => {
if (out[k] === undefined) out[k] = [obj[k]]; //Array doesn't exist yet - instantiate it
else if (!out[k].includes(obj[k])) out[k].push(obj[k]); //Array exists and this value isn't in it - add the value to it
});
return out;
}, {});
};
const filters = getFiltersFromData(data);
console.log(filters.name);
console.log(filters.location);
.as-console-wrapper, .as-console { height: 100% !important; max-height: 100% !important; top: 0; }
You could create the separate arrays from names, locations and values and then use map on the data array to push each attribute value to the arrays. You can do that vs. running map multiple times for each property:
var names = [];
var locations = [];
var values = [];
data.map((elt) => {
names.push(elt.name);
locations.push(elt.location);
values.push(elt.value);
});
Try with Object.entries
You can get something like this:
const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]

Fast way to flatten an array of objects in Javascript

I have an array of generated objects like the following:
[
{obj1: {
key: 'value'
}},
{obj2: {
key: 'value2'
}},
{obj3: {
key: 'value3'
}}
]
I would like to flatten the array, with the following output:
[
{
key: 'value'
},
{
key: 'value2'
},
{
key: 'value3'
}
]
I am doing this with a for loop, which works, but the array will be quite large in size and wonder if there is a more efficient way to do this?
for (var key in array) {
let obj = array[key];
for (var key in obj) {
newArray.push(obj[key]);
}
}
output:
newArray: [
{
key: 'value'
},
{
key: 'value2'
},
{
key: 'value3'
}
]
I'm looking for the simplest method, ES6 or Lodash also welcome for solutions.
Updated to reflect correct array format.
You can simply use reduce and Object.values
let arr = [{obj1: {key: `value`}},{obj2: {key: `value2`
}},{obj3: {key: `value3`}}]
let op = arr.reduce((op,e)=> op.concat(Object.values(e)),[])
console.log(op)
You can use simple for loop when you care about speed.
let arr = [{obj1: {key: `value`}},{obj2: {key: `value2`
}},{obj3: {key: `value3`}}]
let op = []
for(let i=0; i<arr.length; i++){
let values = Object.values(arr[i])
op = op.concat(values)
}
console.log(op)
You can use Array.map, and Object.values.
Map "maps" each element in an array to a new array.
It takes each element of an array, and performs an operation on it.
The result of this operation becomes the corresponding element in a new Array.
This new Array is what's returned.
To convert Objects into Arrays: you can use Object.values, Object.keys, and Object.entries.
Object.values de-references each key in an object, and turns it into an array element holding that key's value.
const arr = [
{obj1: {key: 'value'}},
{obj2: {key: 'value2'}},
{obj3: {key: 'value3'}}
];
let newArr = arr.map(obj => (
{key: Object.values(obj)[0].key}
));
console.log(newArr);
To return an object, it must be wrapped in parenthesis.
In the first iteration, obj == { obj1: { key: 'value' }}, the first element in the input Array, arr.
And,
Object.values(obj) == [{key: 'value'}]
So, we need to grab the element at index 0 to pull the object out of the array {key: 'value'}.
Alternatively, if you know you can rely on the naming structure of the elements in your array (the outer object's key), you could do this, which may be easier to reason about:
const arr = [
{obj1: {key: 'value'}},
{obj2: {key: 'value2'}},
{obj3: {key: 'value3'}}
];
let newArr2 = arr.map( (obj, i) => (
{ key: obj['obj'+(i+1)].key }
));
console.log(newArr2);
Note: you'll need to wrap the i+1 in parenthesis, to force addition to take precedence over JS auto type conversion and string concatenation. Otherwise instead of obj1, obj2, obj3, you'll get obj01, obj11, obj21 as the object keys.

Finding an array object ID by property

This may be a duplicate, but I'm not sure.
I have the following array:
[
{
id: "object1"
},
{
id: "object2"
},
{
id: "object3"
}
]
The trick is, the array is dynamic, and, therefore, the global IDs of this array objects vary. For example, array[1] in one case may be an object with id "object1", and, in other case, that with an id of "object3".
How to query this array based on the id string and have the array index as the output?
reduce into an object indexed by id, with the values being the index of that id's object in the original array, and then you can use simple object lookup:
const input = [
{
id: "object1"
},
{
id: "object2"
},
{
id: "object3"
}
];
const indexedById = input.reduce((a, { id }, i) => {
a[id] = i;
return a;
}, {});
console.log(indexedById.object2); // index of 1 in input
.findIndex is another possibility, but it has worse time complexity than object lookup.
Array has a findIndex, so you could do const findById = (x) => xs.findIndex(({ id }) => id === x) where x is your id string and xs is your array of objects.

How to convert an Object {} to an Array [] of key-value pairs in JavaScript

I want to convert an object like this:
{"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
into an array of key-value pairs like this:
[[1,5],[2,7],[3,0],[4,0]...].
How can I convert an Object to an Array of key-value pairs in JavaScript?
You can use Object.keys() and map() to do this
var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
var result = Object.keys(obj).map((key) => [Number(key), obj[key]]);
console.log(result);
The best way is to do:
var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
var result = Object.entries(obj);
console.log(result);
Calling entries, as shown here, will return [key, value] pairs, as the caller requested.
Alternatively, you could call Object.values(obj), which would return only values.
Object.entries() returns an array whose elements are arrays corresponding to the enumerable property [key, value] pairs found directly upon object. The ordering of the properties is the same as that given by looping over the property values of the object manually.
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Description
The Object.entries function returns almost the exact output you're asking for, except the keys are strings instead of numbers.
const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};
console.log(Object.entries(obj));
If you need the keys to be numbers, you could map the result to a new array with a callback function that replaces the key in each pair with a number coerced from it.
const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};
const toNumericPairs = input => {
const entries = Object.entries(input);
return entries.map(entry => Object.assign(entry, { 0: +entry[0] }));
}
console.log(toNumericPairs(obj));
I use an arrow function and Object.assign for the map callback in the example above so that I can keep it in one instruction by leveraging the fact that Object.assign returns the object being assigned to, and a single instruction arrow function's return value is the result of the instruction.
This is equivalent to:
entry => {
entry[0] = +entry[0];
return entry;
}
As mentioned by #TravisClarke in the comments, the map function could be shortened to:
entry => [ +entry[0], entry[1] ]
However, that would create a new array for each key-value pair, instead of modifying the existing array in place, hence doubling the amount of key-value pair arrays created. While the original entries array is still accessible, it and its entries will not be garbage collected.
Now, even though using our in-place method still uses two arrays that hold the key-value pairs (the input and the output arrays), the total number of arrays only changes by one. The input and output arrays aren't actually filled with arrays, but rather references to arrays and those references take up a negligible amount of space in memory.
Modifying each key-value pair in-place results in a negligible amount of memory growth, but requires typing a few more characters.
Creating a new array for each key-value pair results in doubling the amount of memory required, but requires typing a few less characters.
You could go one step further and eliminate growth altogether by modifying the entries array in-place instead of mapping it to a new array:
const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};
const toNumericPairs = input => {
const entries = Object.entries(obj);
entries.forEach(entry => entry[0] = +entry[0]);
return entries;
}
console.log(toNumericPairs(obj));
To recap some of these answers now on 2018, where ES6 is the standard.
Starting with the object:
let const={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
Just blindly getting the values on an array, do not care of the keys:
const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.values(obj));
//[9,8,7,6,5,4,3,2,1,0,5]
Simple getting the pairs on an array:
const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.entries(obj));
//[["1",9],["2",8],["3",7],["4",6],["5",5],["6",4],["7",3],["8",2],["9",1],["10",0],["12",5]]
Same as previous, but with numeric keys on each pair:
const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.entries(obj).map(([k,v])=>[+k,v]));
//[[1,9],[2,8],[3,7],[4,6],[5,5],[6,4],[7,3],[8,2],[9,1],[10,0],[12,5]]
Using the object property as key for a new array (could create sparse arrays):
const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.entries(obj).reduce((ini,[k,v])=>(ini[k]=v,ini),[]));
//[undefined,9,8,7,6,5,4,3,2,1,0,undefined,5]
This last method, it could also reorganize the array order depending the value of keys. Sometimes this could be the desired behaviour (sometimes don't). But the advantage now is that the values are indexed on the correct array slot, essential and trivial to do searches on it.
Map instead of Array
Finally (not part of the original question, but for completeness), if you need to easy search using the key or the value, but you don't want sparse arrays, no duplicates and no reordering without the need to convert to numeric keys (even can access very complex keys), then array (or object) is not what you need. I will recommend Map instead:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
let r=new Map(Object.entries(obj));
r.get("4"); //6
r.has(8); //true
In Ecmascript 6,
var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};
var res = Object.entries(obj);
console.log(res);
var obj = {
"1": 5,
"2": 7,
"3": 0,
"4": 0,
"5": 0,
"6": 0,
"7": 0,
"8": 0,
"9": 0,
"10": 0,
"11": 0,
"12": 0
};
var res = Object.entries(obj);
console.log(res);
Yet another solution if Object.entries won't work for you.
const obj = {
'1': 29,
'2': 42
};
const arr = Array.from(Object.keys(obj), k=>[`${k}`, obj[k]]);
console.log(arr);
Use Object.keys and Array#map methods.
var obj = {
"1": 5,
"2": 7,
"3": 0,
"4": 0,
"5": 0,
"6": 0,
"7": 0,
"8": 0,
"9": 0,
"10": 0,
"11": 0,
"12": 0
};
// get all object property names
var res = Object.keys(obj)
// iterate over them and generate the array
.map(function(k) {
// generate the array element
return [+k, obj[k]];
});
console.log(res);
Use Object.entries to get each element of Object in key & value format, then map through them like this:
var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
var res = Object.entries(obj).map(([k, v]) => ([Number(k), v]));
console.log(res);
But, if you are certain that the keys will be in progressive order you can use Object.values and Array#map to do something like this:
var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};
// idx is the index, you can use any logic to increment it (starts from 0)
let result = Object.values(obj).map((e, idx) => ([++idx, e]));
console.log(result);
You can use Object.values([]), you might need this polyfill if you don't already:
const objectToValuesPolyfill = (object) => {
return Object.keys(object).map(key => object[key]);
};
Object.values = Object.values || objectToValuesPolyfill;
https://stackoverflow.com/a/54822153/846348
Then you can just do:
var object = {1: 'hello', 2: 'world'};
var array = Object.values(object);
Just remember that arrays in js can only use numerical keys so if you used something else in the object then those will become `0,1,2...x``
It can be useful to remove duplicates for example if you have a unique key.
var obj = {};
object[uniqueKey] = '...';
With lodash, in addition to the answer provided above, you can also have the key in the output array.
Without the object keys in the output array
for:
const array = _.values(obj);
If obj is the following:
{ “art”: { id: 1, title: “aaaa” }, “fiction”: { id: 22, title: “7777”} }
Then array will be:
[ { id: 1, title: “aaaa” }, { id: 22, title: “7777” } ]
With the object keys in the output array
If you write instead ('genre' is a string that you choose):
const array= _.map(obj, (val, id) => {
return { ...val, genre: key };
});
You will get:
[
{ id: 1, title: “aaaa” , genre: “art”},
{ id: 22, title: “7777”, genre: “fiction” }
]
If you are using lodash, it could be as simple as this:
var arr = _.values(obj);
var obj = { "1": 5, "2": 7, "3": 0, "4": 0, "5": 0, "6": 0, "7": 0, "8": 0, "9": 0, "10": 0, "11": 0, "12": 0 }
let objectKeys = Object.keys(obj);
let answer = objectKeys.map(value => {
return [value + ':' + obj[value]]
});
const persons = {
john: { age: 23, year:2010},
jack: { age: 22, year:2011},
jenny: { age: 21, year:2012}
}
const resultArray = Object.keys(persons).map(index => {
let person = persons[index];
return person;
});
//use this for not indexed object to change array
This is my solution, i have the same issue and its seems like this solution work for me.
yourObj = [].concat(yourObj);
or you can use Object.assign():
const obj = { 0: 1, 1: 2, 2: 3};
const arr = Object.assign([], obj);
console.log(arr)
// arr is [1, 2, 3]
Here is a "new" way with es6 using the spread operator in conjunction with Object.entries.
const data = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};
const dataSpread = [...Object.entries(data)];
// data spread value is now:
[
[ '1', 5 ], [ '2', 7 ],
[ '3', 0 ], [ '4', 0 ],
[ '5', 0 ], [ '6', 0 ],
[ '7', 0 ], [ '8', 0 ],
[ '9', 0 ], [ '10', 0 ],
[ '11', 0 ], [ '12', 0 ]
]
you can use 3 methods convert object into array (reference for anyone not only for this question (3rd on is the most suitable,answer for this question)
Object.keys() ,Object.values(),andObject.entries()
examples for 3 methods
use Object.keys()
const text= {
quote: 'hello world',
author: 'unknown'
};
const propertyNames = Object.keys(text);
console.log(propertyNames);
result
[ 'quote', 'author' ]
use Object.values()
const propertyValues = Object.values(text);
console.log(propertyValues);
result
[ 'Hello world', 'unknown' ]
use Object.entires()
const propertyValues = Object.entires(text);
console.log(propertyValues);
result
[ [ 'quote', 'Hello world' ], [ 'author', 'unknown' ] ]
Use for in
var obj = { "10":5, "2":7, "3":0, "4":0, "5":0, "6":0, "7":0,
"8":0, "9":0, "10":0, "11":0, "12":0 };
var objectToArray = function(obj) {
var _arr = [];
for (var key in obj) {
_arr.push([key, obj[key]]);
}
return _arr;
}
console.log(objectToArray(obj));
Recursive convert object to array
function is_object(mixed_var) {
if (mixed_var instanceof Array) {
return false;
} else {
return (mixed_var !== null) && (typeof( mixed_var ) == 'object');
}
}
function objectToArray(obj) {
var array = [], tempObject;
for (var key in obj) {
tempObject = obj[key];
if (is_object(obj[key])) {
tempObject = objectToArray(obj[key]);
}
array[key] = tempObject;
}
return array;
}
We can change Number to String type for Key like below:
var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
var result = Object.keys(obj).map(function(key) {
return [String(key), obj[key]];
});
console.log(result);
you can use _.castArray(obj).
example:
_.castArray({ 'a': 1 });
// => [{ 'a': 1 }]

How to make `Object.keys` respect the order in which keys are 'declared' in an object?

Given the object:
var opts = {
'all': 'All',
0: 'Some option',
1: 'Cookies',
};
Object.keys(opts) returns this:
["0", "1", "all"]
When I'm expecting this:
["all", "0", "1"] // The order in which the keys are 'declared' in the obj
How can I iterate through the properties in the order in which they appear in the object?
Thanks.
ECMA-262, section 12.6.4 about the for-in statement:
The mechanics and order of enumerating the properties (step 6.a in the first algorithm, step 7.a in the second) is not specified.
You could use array instead:
var opts = [
{key: 'all', value: 'All'},
{key: 0, value: 'Some option'},
{key: 1, value: 'Cookies'}
];
Or, in ES6, the Map object:
var opts = new Map([
['all', 'All'],
[0, 'Some option'],
[1, 'Cookies']
]);
opts.forEach(function(val, key) {
console.log(key, val);
});
In which case forEach will always iterate key-value pairs in insertion order.
No, properties order in objects are not guaranted in JavaScript, you need to use an Array.
Does JavaScript Guarantee Object Property Order?

Categories

Resources