Destructuring for get the first property of an object? - javascript

For arrays, we can define the properties depending on it's indexes like:
const arr = [1, 2, 3];
const [first, second, third] = arr;
console.log(first, second, third)
I'm just wondering if there's a possible solution to do it's reverse with objects like:
const obj = {first: "a", second: "b", third: "c"}
const {0, 1, 2} = obj;
//expected: "a", "b", "c"

You do it like this for objects:
const obj = {foo: 123, bar: 'str'}
const {foo, bar} = obj

It isn't.
Objects are not designed to be ordered, so there isn't a first property per se.
You could convert an object into an array of its values first …
const obj = {
first: "a",
second: "b",
third: "c"
}
const array = Object.values(obj);
const [foo, bar, baz] = array;
console.log({
foo,
bar,
baz
});
… but it is unlikely to be useful and it certainly wouldn't be intuitive code that is easy to maintain.

Try this:
const obj = {first: "a", second: "b", third: "c"}
const indexes = [0, 1, 2]
indexes.map( (val) => { return Object.values(obj)[val] } ) //["a", "b", "c"]

You could take the values and assign this to an array for destructuring.
The order is actually dtermined by the insertation order or if a key is like a valid index of an array, it is sorted numerically to top.
const
object = { first: "a", second: "b", third: "c" },
[first, second, third] = Object.values(object);
console.log(first, second, third);
For extracting a an arbitrary position, you vould take an object with an index an object property assignment pattern [YDKJS: ES6 & Beyond] for a new valid variable.
const
object = { first: "a", second: "b", third: "c" },
{ 2: foo } = Object.values(object);
console.log(foo);

Related

Can I combine spread and rest in destructuring object in Javascript?

Let us have this object:
// Values of properties are irelevant
let row = {_x: "x", _y: "y", _z: "z", a: "a", b: "b"}
I need to get copy of this object without properties beginning with underscore (_).
I can do this:
const {_x, _y, _z, ...pureRow} = row;
console.log(pureRow); // {a: "a", b: "b"}
But I would like to have a list of removed properties in an array and remove all properties listed in this array. Something like:
const auxFields = ["_x", "_y", "_z"];
const {...auxFields, ...pureRow} = row; // Error: A rest element must be last in a destructuring pattern.
console.log(pureRow); // {a: "a", b: "b"}
Is there some way to achieve this?

How to use ES6 destructuring assignment to assign one object to another

I need the value of keys in object arrA to be copied from arrB based on key name. Here are my two objects:
let arrA = {
'aaa':'',
'bbb':'',
'ccc':''
}
let arrb = {
'aaa':'111',
'bbb':'222',
'ccc':'333',
'ddd':'444',
'eee':'555',
...
}
How do I do this with the ES6 deconstructive assignment:
arrA = {
'aaa':'111',
'bbb':'222',
'ccc':'333'
}
Using destructing assignment, you'd have to explicitly define each property you'd want to copy:
let arra = {
'aaa': '',
'bbb': '',
'ccc': ''
};
let arrb = {
'aaa': '111',
'bbb': '222',
'ccc': '333',
'ddd': '444',
'eee': '555',
};
({aaa: arra.aaa, bbb: arra.bbb, ccc: arra.ccc} = arrb);
console.log(arra);
However, this code is very repetitive, and the worst part is that it's explicit with what gets copied.
The purpose of destructuring is to pull out variables from the object into your local scope. Learn more about destructuring here. You're probably better off solving this problem with different tools.
Using a combination of different functions, you can do this instead:
let arra = {
'aaa':'',
'bbb':'',
'ccc':''
}
let arrb = {
'aaa':'111',
'bbb':'222',
'ccc':'333',
'ddd':'444',
'eee':'555'
}
const result = Object.fromEntries(
Object.keys(arra)
.map(key => [key, arrb[key]])
)
console.log(result)
First, I'm grabbing all of the keys from arra with Object.keys(), then I'm creating a list of pairs using the .map() function, and finally I'm turning the pairs into a new object with Object.fromEntries()
Lodash's pick() is your friend here (because life is too short to write boring boilerpllate code):
You just npm install lodash and say:
const _ = require('lodash');
_.pick( sourceObjectOrArray, arrayOfDesiredPaths );
Like this:
const _ = require('lodash');
const source = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
f: 6,
g: 7,
}
const picked = _.pick( source, ['a','c','e'] );
console.log( JSON.stringify(picked) );
And you'll find picked is what you'd expect:
{
a: 1,
c: 3,
e: 5
}

Get same section of two objects in different type

I'd like to find best practice for getting the same section of two objects
const firstObject = { a: 1, b: 2, c: 3}
const secondObject = { 1, 2 }
// desired result: { a: 1, b: 2} or simply { a, b }
In my opinion, we need to do three steps:
1) Get value all values of each object
Object.values = Object.values || (obj => Object.keys(obj).map(key => obj[key]))
2) Find the same section from two arrays value
3) Find key-value pair from firstObject
Any other ways to do it?
Using Standard built-in objects as Array or Object is preferable
Break the firstObject into [key, value] pairs using Object#entries (or polyfill), and use Array#reduce to combine all those that exist in the secondObject.
const firstObject = { a: 1, b: 2, c: 3}
const secondObject = { 1: 1, 2: 2 };
const result = Object.entries(firstObject).reduce((obj, [key, value]) => {
value in secondObject && (obj[key] = value);
return obj;
}, {})
console.log(result);
Object.keys(firstObject).filter(key=> key in secondObject).reduce((o,k)=>(o[k]=firstObject[k],o),{});

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 }]

Convert an array to nested object using Lodash, is it possible?

I have an array:
["a", "b", "c", "d"]
I need to convert it to an object, but in this format:
a: {
b: {
c: {
d: 'some value'
}
}
}
if var common = ["a", "b", "c", "d"], I tried:
var objTest = _.indexBy(common, function(key) {
return key;
}
);
But this just results in:
[object Object] {
a: "a",
b: "b",
c: "c",
d: "d"
}
Since you're looking for a single object out of an array, using _.reduce or _.reduceRight is a good candidate for getting the job done. Let's explore that.
In this case, it's going to be hard to work from left to right, because it will require doing recursion to get to the innermost object and then working outward again. So let's try _.reduceRight:
var common = ["a", "b", "c", "d"];
var innerValue = "some value";
_.reduceRight(common, function (memo, arrayValue) {
// Construct the object to be returned.
var obj = {};
// Set the new key (arrayValue being the key name) and value (the object so far, memo):
obj[arrayValue] = memo;
// Return the newly-built object.
return obj;
}, innerValue);
Here's a JSFiddle proving that this works.

Categories

Resources