My code:
const users = [ { id: 1, name: 'user1' }, { id: 2, name: 'user2' } ]
p = new Promise( resolve => resolve(users) )
p.then( (user) => console.log(user) )
Return me the following logs:
[ { id: 1, name: 'user1' }, { id: 2, name: 'user2' } ]
If I change it as below,
users.then( ([user]) => console.log(user) )
I receive the following logs:
{ id: 1, name: 'user1' }
I don't quite understand why the second one only logs the first element in the array.
It's a destructuring assignment
[a, b, c] = [1, 2, 3]
console.log(a)
console.log(b)
console.log(c)
but if you only destructure one, you get the first value of the array
[a] = [1, 2, 3]
console.log(a)
As for your example, destructuring can be done in many places such as function arguments
Destructuring is an ES6 aka ECMA2015 features.
You can destructure Array and Objects.
Object destructuring as bellow, allow you to pick up the keys you want to get from an object using easy syntax.
const obj = {
a: 'a',
b: 'b',
c: 'c',
};
// Without object destructuring
const a_ = obj.a;
const b_ = obj.b;
// With object destructuring
const {
a,
b,
} = obj;
console.log(a);
Array destructuring is quite the same, but instead of specifying the keys you want to get, you use the index of the data.
const arr = [
'a',
'b',
'c',
];
// Without array destructuring
const a_ = arr[0];
const c_ = arr[2];
// With array destructuring
const [
a, , c,
] = arr;
console.log(c);
You can use Array and Object destructuring anywhere; including in function parameters. It's especially good in this case because you can assign default value easily to keys, as bellow
function func({
a,
b,
c = 'default',
}) {
console.log(a, '/', b, '/', c);
}
func({
a: 'j\'aime la france',
b: 'vive les baguettes',
});
Related
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)
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);
How is it possible to set the same value on multiple keys? For example I have the following object:
const obj = {
a: 5,
b: 5,
c: 5,
d: 6
}
Is there any easy way for example lets say I have array of [a, b, c] (keys) and to spread them in object and set them as keys with same value. Point is to look more classy for example:
const keys =[a, b, c]
const obj = {
[...keys]: 5
}
I know this would throw error but looking for some shorthand to achieve this
Take the array of keys and map each to an entry of the key and the 5 value:
const keys = ['a', 'b', 'c'];
const obj = {
...Object.fromEntries(
keys.map(key => [key, 5])
),
d: 6
};
console.log(obj);
Something like this works:
const obj = {};
const value = 5;
['a', 'b', 'c'].forEach(key => obj[key] = value);
You can build a zip function which takes an array of keys and a array of values and returns an object where each key/value pair is taken from their respective index:
const zip =
(ks, vs) =>
ks.reduce((o, k, i) =>
(o[k] = vs[i], o), {});
zip(['a', 'b', 'c'], [5, 5, 5]);
//=> {a: 5, b: 5, c: 5}
If you need to generate an array of 5:
Array(3).fill(5);
//=> [5, 5, 5]
Another solution could take a spreading of Object.assign with a spreaded array of objects.
const
keys = ['a', 'b', 'c'],
obj = { ...Object.assign(...keys.map(k => ({ [k]: 5 }))), d: 6 };
console.log(obj);
function(item)
{
return Object.keys(item).reduce((a, b) => ({ ...a, [b]:5 }),{});
}
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);
I'm trying to write a function that takes an array of objects, and an unlimited number of arrays, and combines them to form a single object. The inputs would follow this pattern:
let x = [{ name: 'Tom' }, { name: 'John' }, { name: 'Harry' }];
let y = [[1, 2, 3], 'id'];
let z = [['a', 'b', 'c'], 'value'];
combine(x, y, z);
With the second element of y and z acting as the object key. Using these arguments, the function should return the following array:
[
{
name: 'Tom',
id: 1,
value: 'a'
},
{
name: 'John',
id: 2,
value: 'b'
},
{
name: 'Harry',
id: 3,
value: 'c'
},
]
The index of the current object should be used to get the correct element in the array. I have made an attempt at the problem:
function combine(object, ...arrays) {
return object.map((obj, index) => {
let items = arrays.map(arr => ({
[arr[1]]: arr[0][index]
}));
return Object.assign({}, obj, { items });
});
}
This almost does the job, but results in the array items being hidden inside a nested items array, How can I solve this?
You had been assigning an object of object, and the result was a new object with the element items inside (another feature of object literal).
This approach use reduce instead of map and direct assign instead of object literal.
function combine(object, ...arrays) {
return object.map((obj, index) => {
const items = arrays.reduce((acc, arr) => {
acc[arr[1]] = arr[0][index] ;
return acc;
}, {});
return Object.assign({}, obj, items);
});
}
const x = [{ name: 'Tom' }, { name: 'John' }, { name: 'Harry' }];
const y = [[1, 2, 3], 'id'];
const z = [['a', 'b', 'c'], 'value'];
combine(x, y, z);
You can also use the spread operator in the Object.assign, like this:
function combine(object, ...arrays) {
return object.map((obj, index) => {
let items = arrays.map(arr => ({
[arr[1]]: arr[0][index]
}));
return Object.assign({}, obj, ...items);
});
}
This almost does the job, but results in the array items being hidden inside a nested items array
The problem is that items is an array, whereas you only need the current item inside of that particular map callback. No need to nest loops here.
Also I would recommend avoiding multiple properties per combine call. The resulting code would look like this:
function combine(objects, [values, key]) {
return objects.map((o, i) =>
Object.assign({[key]: values[i]}, o)
);
}
combine(combine(x, y), z);
If you then have multiple extensions to do, you can also use
[y, z].reduce(combine, x)
With map and computed keys, you can achieve this.
Here's a working example:
let x = [{
name: 'Tom'
}, {
name: 'John'
}, {
name: 'Harry'
}];
let y = [[1, 2, 3], 'id'];
let z = [['a', 'b', 'c'], 'value'];
let result = [];
x.map(function (el, index) {
result.push(el);
let index = result.length -1;
result[index][y[1]] = y[0][index];
result[index][z[1]] = z[0][index];
});
console.log(result);