Related
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 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 );
I have one strange question about Destructuring in the JS. How can I get object from another object, only with needed keys.
For example, to transform this object:
let firstObj = {
a: 1,
b: 2,
c: 3,
d: 4
};
To this:
let secondObj = {
a: 1,
d: 4
};
I have array with first type objects. For some reasons I should to use minimal code for this.
My minimum code:
arrayObj = [firstObj, firstObj, firstObj, firstObj, firstObj];
let secondArr = arrayObj.map(
({a, d}) => ({a, d})
);
How can I improve this one?
You could use an IIFE for takeing the wanted properties and return a new object.
var first = { a: 1, b: 2, c: 3, d: 4 },
second = (({ a, d }) => ({ a, d }))(first);
console.log(second);
With an array of keys for a dynamic approach
var first = { a: 1, b: 2, c: 3, d: 4 },
keys = ['a', 'd']
second = Object.assign(...keys.map(k => ({ [k]: first[k] })));
console.log(second);
You can create a array with your needed keys and use reduce() on that array to get values from firstObj.
DEMO
const neededKeys = ['a', 'd'],
firstObj = {a: 1,b: 2,c: 3,d: 4};
let result = neededKeys.reduce((r, v) => Object.assign(r,{[v]:firstObj[v]}), {});
console.log(result);
.as-console-wrapper {max-height: 100% !important;top: 0;}
const state = [
{10: {a: 22, b: 33}},
{12: {a: 20, b: 33}},
{15: {a: 22, b: 34}},
{5: {a: 21, b: 30}},
{9: {a: 29, b: 33}},
]
State is an array of objects like above. When the app updates an object, the object should flow up to the first position.
E.g. let's say that we take the second object above (with the primary key 12), and copy and update it so it looks like this:
{12: {a: 45, b: 33}}
And now we want to insert it to the array with the following result:
const state = [
{12: {a: 45, b: 33}},
{10: {a: 22, b: 33}},
{15: {a: 22, b: 34}},
{5: {a: 21, b: 30}},
{9: {a: 29, b: 33}},
]
I understand how to update an object in an immutable fashion, but I cannot get my head around how to accomplish the above.
You could use something like
// an update function, here it just adds a new key
// to the object
const update = (x) => ({
...x,
hello: "world"
});
// a filter factory
const withId = (id) => (item) => Boolean(item[id]); // item with specific ids
const withoutId = (id) => (item) => !Boolean(item[id]); // others
const state = [
{10: {a: 22, b: 33}},
{12: {a: 20, b: 33}},
{15: {a: 22, b: 34}},
{5: {a: 21, b: 30}},
{9: {a: 29, b: 33}},
];
const id = 5;
const newState = state
.filter(withId(id))
.map(update)
.concat(state.filter(withoutId(id)));
console.log(JSON.stringify(newState, null, 4));
What this does is filtering the state between the items you want to update and the rest, apply the update to the selection and concat the untouched items to them.
Below another example on with the same idea which illustrates that you can perform the update on more than one item :
const markAsDone = (todo) => ({
...todo,
done: true
});
const isInGroup = (group) => (todo) => todo.group === group;
const not = (predicate) => (x) => !predicate(x);
const isWork = isInGroup("work");
const notWork = not(isWork);
const state = [
{
todo: "go shopping",
group: "life"
},
{
todo: "go work",
group: "work",
},
{
todo: "go sleep",
group: "life"
}
];
// get work related todos, mark as done and
// append to todo list
const newState = state
.filter(notWork)
.concat(state
.filter(isWork)
.map(markAsDone));
console.log(JSON.stringify(newState, null, 4));
something like this perhaps?
const state = [
{10: {a: 22, b: 33}},
{12: {a: 20, b: 33}},
{15: {a: 22, b: 34}},
{5: {a: 21, b: 30}},
{9: {a: 29, b: 33}},
]
// find the numerical index of the object with the specified "key"
function findIndexOfKey(array, key){
return array.findIndex(function(el){return key in el});
}
// modify object and move to front
function editObjectAndMoveToFront(array, key, updatedValues){
// find index of object with key, for use in splicing
var index = findIndexOfKey(array, key);
// create the updated version of the specified object
var originalObject = array[index];
var originalObjectValue = originalObject[key];
var editedObject = {};
editedObject[key] = Object.assign({}, originalObjectValue, updatedValues)
// here is the new state, with the updated object at the front
var newArray = [
editedObject,
...array.slice(0, index),
...array.slice(index + 1)
]
return newArray
}
const newState = editObjectAndMoveToFront(state, 12, {a: 45, b: 33})
console.log(newState);
Say I have an object like this:
object_1 = {
a: 10,
b: 5,
c: 15
};
Is there a quick way to create another object that only has the same keys, like?
object_2 = {
a: 0,
b: 0,
c: 0
}
I know Object.keys(object_1) gives me an array with the keys but I don't know how to assign them as keys in the new object.
object_2 = Object.assign({}, Object.keys(object_1))
If I could somehow invert that array that would work :D
You could use Object.assign with mapped objects and spread syntax ... and computed property names.
var object1 = { a: 10, b: 5, c: 15 },
object2 = Object.assign(...Object.keys(object1).map(k => ({ [k]: 0 })));
console.log(object2);
You can iterate the keys of the object with Array#reduce, and create a new object:
var object_1 = {
a: 10,
b: 5,
c: 15
};
var object_2 = Object.keys(object_1).reduce((o, k) => (o[k] = 0, o), {});
console.log(object_2);
You can use .reduce as above or forEach to create a new object with the same keys and initialized values like below (This is without arrow function and other spread operator related to ES6)
var object_2 = {};
object_1 = {
a: 10,
b: 5,
c: 15
};
Object.keys(object_1).forEach( function(x){ object_2[x] = 0});
console.log(object_2);