How to destructure an array from inside an object in javascript? - javascript

I have an object like this:
obj = {'id': 1, a: [1, 2, 3]}
I want to destructure and get the array a from obj
arr = {...obj.a}
I get:
{0: 1, 1: 2, 2: 3}
which is not an array
How to get the array itself ?

You are spreading an array inside {}. This creates an object with indices of the array as keys. This is why you get {0: 1, 1: 2, 2: 3}
const a = [ 1, 2 ]
console.log({ ...a })
If you want to get a property into a variable, this is the correct syntax:
const { propertyName } = yourObject
// if you want to have a variable name which is different than the propertyName
const { propertyName: someOtherVariable } = yourObject
Here's the working snippet:
const obj = {'id': 1, a: [1, 2, 3] }
const { a: arr } = obj; // this is same as: const arr = obj.a
console.log(arr)

Almost - it's the other way round :)
let {a: arr} = {'id': 1, a: [1, 2, 3]}

You could destructure to an array by assigning the array to an array with a rest syntax.
var obj = { id: 1, a: [1, 2, 3] },
[...arr] = obj.a;
console.log(arr);

Use brackets instead of curly braces to spread it into a new array:
const obj = {'id': 1, a: [1, 2, 3]}
const arr = [...obj.a]
console.log(arr)

Related

Reordering an object to the keys are in the same order as an array

I have an array that looks like this,
['event_tag', 'workflow_tag', 'created_timestamp', 'success']
and an array of objects where the object looks like,
{
"created_timestamp": "2022-04-01T13:14:53.028002Z",
"workflow_tag": "dj807",
"event_tag": "refresh",
"success": true
}
What I am wanting to do is make the above object and any other objects in that array match the order of the values in the first array so the finished object should look like,
{
"event_tag": "refresh",
"workflow_tag": "dj807",
"created_timestamp": "2022-04-01T13:14:53.028002Z",
"success": true
}
I have tried the following so far,
const keys = ['event_tag', 'workflow_tag', 'created_timestamp', 'success'];
newRowData = parsedRows.reduce((obj, v) => {
obj[v] = keys[v];
return obj
}, {});
But this returns,
{[object Object]: undefined}
You could order the keys by constructing a new object inside of an Array#map:
const parsedRows = [ { a: 1, c: 3, d: 4, b: 2, }, { b: 6, a: 5, c: 7, d: 8, }, { d: 12, b: 10, a: 9, c: 11, }, ];
const order = ['a', 'b', 'c', 'd'];
let newData = parsedRows.map(row => {
let newRow = {};
for (let key of order) {
newRow[key] = row[key];
}
return newRow;
});
console.log(newData);
Instead of iterating over Rows, Iterate on keys either map/reduce.
const keys = ["event_tag", "workflow_tag", "created_timestamp", "success"];
const obj = {
created_timestamp: "2022-04-01T13:14:53.028002Z",
workflow_tag: "dj807",
event_tag: "refresh",
success: true,
};
const res = Object.assign({}, ...keys.map((key) => ({ [key]: obj[key] })));
console.log(res)

JavaScript, split object in 2, and push in array

I have an array of objects like this:
const arrayOfObjects = [
{ A: 1, B: 2, C: 3 },
{ A: 3, B: 4, C: 1 }
]
And another array which is called "headers"
const headers = [
['A', 'B'],
['C']
]
I have to create an array similar to the first one but, with those objects splited by what headers have in it's arrays.
This should be the goal:
const result = [
[
{ A: 1, B: 2 },
{ C: 3 }
],
[
{ A: 3, B: 4 },
{ C: 1 }
]
]
I tried by doing a "base" array with:
const baseArray = []
headers.forEach((header) => {
const objFromHeader = {};
header.forEach((head) => {
objFromHeader[head] = 0;
});
baseArray.push(objFromHeader);
});
That will give me the result array but with 0 values for each key.
And then loop for the first array and put inside another array the base array with the correct values.
Then I wanted to fill each key according to the value that comes from arrayOfObjects but here is where I can't see how could I loop that array of objects and put the correct value. The only problem with that approach is that the result array will have some 0 values that come from the initiation array that I'm using, it would be better to me to only put the objects that actually have values and not 0 (I was thinking on another function to delete those keys with value = 0...)
How could I achieve it in a better way?
Fiddle:
https://jsfiddle.net/pmiranda/Lpscz6vt/
When iterating over an object, use findIndex on the headers to identify which index in the headers array the property being iterated over should go into. Create an object there if it doesn't exist yet, and set the property.
const arrayOfObjects = [
{ A: 1, B: 2, C:3 },
{ A: 3, B: 4, C:1 }
];
const headers = [
['A', 'B'],
['C']
];
const toResultItem = (object) => {
const resultItem = [];
for (const [key, value] of Object.entries(object)) {
const headersIndex = headers.findIndex(arr => arr.includes(key));
resultItem[headersIndex] ??= {};
resultItem[headersIndex][key] = value;
}
return resultItem;
};
console.log(arrayOfObjects.map(toResultItem));
const arrayOfObjects = [
{ A: 1, B: 2, C: 3 },
{ A: 3, B: 4, C: 1 },
];
const headers = [['A', 'B'], ['C', 'D']];
const result = arrayOfObjects.map((obj) =>
headers.map((header) =>
header.reduce((acc, key) => {
acc[key] = obj[key];
return Object.keys(acc).reduce((newAcc, key) => {
if (acc[key]) {
newAcc[key] = acc[key];
}
return newAcc;
}
, {});
}, {})
)
);
console.log(result);
Array.forEach implementation
Logic
Loop through arrayOfObjects array.
Inside that, loop through headers array.
Inside that, loop through each array in the headers array.
Create an empty object and assign the property from nodes in headers array with values from objects in arrayOfObjects array.
const arrayOfObjects = [
{ A: 1, B: 2, C: 3 },
{ A: 3, B: 4, C: 1 }
];
const headers = [
['A', 'B'],
['C']
];
const baseArray = []
arrayOfObjects.forEach((obj) => {
const childNode = [];
headers.forEach((head) => {
const node = {};
head.forEach((key) => node[key] = obj[key]);
childNode.push(node);
});
baseArray.push(childNode);
});
console.log(baseArray)
Array.map and Array.reduce implementation.
Using the same logic implementes in the above solution, we can rewrite this using Array.map and Array.reduce as below.
const arrayOfObjects = [
{ A: 1, B: 2, C: 3 },
{ A: 3, B: 4, C: 1 }
];
const headers = [
['A', 'B'],
['C']
];
const output = arrayOfObjects.map((obj) => {
return headers.map((header) => {
return header.reduce((acc, curr) => {
acc[curr] = obj[curr];
return acc;
}, {});
})
})
console.log(output);

array of objects manipulation in js

I have an array of object as below.
data: [ {col: ['amb', 1, 2],} , {col: ['bfg', 3, 4], },]
From above, I need to get array of array as below.
[ [{a: 'amb',b: [1], c: 'red'}, {a: 'amb',b: [2], c: 'orange'}],
[{a: 'bfg',b: [3], c: 'red'}, {a: 'bfg',b: [4], c: 'orange'}]
]
My attempt is as below.
let arrInner: Array<any> = []
let arrOuter: Array<Array<any>> = []
_.forEach(data, (item, i) => {
//create two objects redObj and orangeObj
redObj = {
a: item.col[0].toString(),
b: [item.col[1] as number],
c: 'red'
}
orangeObj = {
a: item.col[0].toString(),
b: [item.col[2] as number],
c: 'orange'
}
//put those two objects to array
arrInner.push(redObj)
arrInner.push(orangeObj)
//assign that array to another array
arrOuter[i] = arrInner
})
But when I print the arrOuter, it is not my expected output. Where I was wrong and how can I fix this?
You need to create a new arrInner each time through the forEach loop. Then push that onto arrOuter.
let arrOuter: Array <Array <any>> = []
_.forEach(data, (item, i) => {
//create two objects redObj and orangeObj
redObj = {
a: item.col[0].toString(),
b: [item.col[1] as number],
c: 'red'
}
orangeObj = {
a: item.col[0].toString(),
b: [item.col[2] as number],
c: 'orange'
}
//put those two objects to array
let arrInner = [redObj, orangeObj]
//assign that array to another array
arrOuter.push(arrInner)
})

How to map more than one property from an array of objects [duplicate]

This question already has answers here:
Extract certain properties from all objects in array
(5 answers)
Closed 4 months ago.
I have an array of Object as follows:
var obj = [
{a: 1, b: 5, c: 9},
{a: 2, b: 6, c: 10},
{a: 3, b: 7, c: 11},
{a: 4, b: 8, c: 12}
];
I know about how to get single object using Array.map() like this.
var result = obj.map(x=>x.a)
This will give me following result
[1, 2, 3, 4]
But I want result like follows:
[
{a: 1, b: 5},
{a: 2, b: 6},
{a: 3, b: 7},
{a: 4, b: 8}
]
In short, from an array of objects I want to select only a few fields (more than one).
How can I do that?
You can use .map() with Object Destructuring:
let data = [
{a:1,b:5,c:9}, {a:2,b:6,c:10},
{a:3,b:7,c:11}, {a:4,b:8,c:12}
];
let result = data.map(({ a, b }) => ({a, b}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If, as in your example, you want to exclude a particular property or few, you can use destructuring and use rest properties to create an object with only the properties you want:
var obj = [
{a:1,b:5,c:9},
{a:2,b:6,c:10},
{a:3,b:7,c:11},
{a:4,b:8,c:12}
];
const mapped = obj.map(({ c, ...rest }) => rest);
console.log(mapped);
If you want to include properties, simply extract them from the .map callback:
var obj = [
{a:1,b:5,c:9},
{a:2,b:6,c:10},
{a:3,b:7,c:11},
{a:4,b:8,c:12}
];
const mapped = obj.map(({ a, b }) => ({ a, b }));
console.log(mapped);
Use map():
var data = [
{a:1,b:5,c:9},
{a:2,b:6,c:10},
{a:3,b:7,c:11},
{a:4,b:8,c:12}
];
let modified = data.map(obj => ({a: obj.a, b: obj.b}))
console.log(modified);
Or if you prefer destructuring:
var data = [
{a:1,b:5,c:9},
{a:2,b:6,c:10},
{a:3,b:7,c:11},
{a:4,b:8,c:12}
];
let modified = data.map(({ a, b }) => ({a, b}));
console.log(modified);
var obj = [
{a: 1, b: 5, c: 9},
{a: 2, b: 6, c: 10},
{a: 3, b: 7, c: 11},
{a: 4, b: 8, c: 12}
];
var result = obj.map(e => ({a:e.a , b:e.b}));
console.log(result)
You can return a custom object with required properties using map()
var obj = [{a:1,b:5,c:9},
{a:2,b:6,c:10},
{a:3,b:7,c:11},
{a:4,b:8,c:12}
];
let op = obj.map(e => {
return { a:e.a, b: e.b };
})
console.log(op);
In your solution for producing [1,2,3,4], x.a isn’t some micro-syntax, it’s actually a full-fledged JavaScript expression. So you can just replace it with the JavaScript for creating a new object with the properties you want.
var result = obj.map(x=>{a: x.a, b: x.b});
... almost. The additional complication is that a { after a => is interpreted as the beginning of a function body, not the beginning of an object literal. You can avoid this by just wrapping the object literal in otherwise-noop parenthesis.
var result = obj.map(x=>({a: x.a, b: x.b}));
You can make your own custom function for this, and pass it a set of properties which you want to extract. :
var array = [{a:1,b:5,c:9}, {a:2,b:6,c:10}, {a:3,b:7,c:11}, {a:4,b:8,c:12} ];
function extractProperties(arr, properties){
return arr.map((obj)=> Object.keys(obj).reduce((acc,key)=>{
if(properties.has(key))
acc[key] = obj[key];
return acc;
},{}));
}
let set = new Set(["a","b"]);
let result = extractProperties(array, set);
console.log(result);
set.add("c");
console.log("**************result2**********")
let result2 = extractProperties(array, set);
console.log(result2);

Select one property from Map.values()

I would like to have something like this:
let myMap = new Map<string, any>();
myMap.set("aaa", {a: 1, b: 2, c:3});
myMap.set("bbb", {a: 1, b: 2, c:6});
myMap.set("ccc", {a: 1, b: 2, c:9});
let cs = myMap.values().map(x => x.c);
Selecting the c property from all entries from the map. This is failing with:
Property 'map' does not exist on type 'IterableIterator<any>'.
Any elegant solution for this?
You can use Array.from() to turn any iterable into an array:
let myMap = new Map();
myMap.set("aaa", {a: 1, b: 2, c:3});
myMap.set("bbb", {a: 1, b: 2, c:6});
myMap.set("ccc", {a: 1, b: 2, c:9});
// Basic example
let cs = Array.from( myMap.values() ).map(x => x.c);
console.log( cs );
// Array.from also takes a mapping function as the second parameter, so even shorter:
let cs_alt = Array.from( myMap.values(), x => x.c );
console.log( cs_alt );

Categories

Resources