I have an array of nested objects, like so:
const objArr = [{obj, obj, objIWant}, {obj, obj, objIWant}, {obj, obj, objIWant}]
Is there a way to get to objIWant without having to loop twice like:
ObjArr.map((obj)=> obj.map(({ objIWant }) => myFunc(objIWant)))
I was hoping I could perhaps leverage destructuring but trying something like [{ objIWant }] = objArr only returns the first objIWant. Am I missing something about destructuring syntax that would allow for this? Many thanks!
No - the only way to do it is with nested map calls.
ObjArr.map(obj => obj.map(({ objIWant }) => myFunc(objIWant));
If you are able to do so, you could change myFunc:
myFunc({ objIWant }) {...}
And then change your code to do this:
ObjArr.map(obj => obj.map(myFunc));
But there's no way using destructuring to do what you're asking.
Destructuring will not make it look cleaner. This is the only way to destructure the properties you want. Using the map function as you are now is a cleaner way of doing it.
const objArr = [{obj:1, obj2:2, objIWant:3}, {obj:4, obj2:5, objIWant:6}, {obj:7, obj2:8, objIWant:9}];
const [{objIWant}, {objIWant:test2}, {objIWant:test3}] = objArr;
window.console.log(objIWant);
window.console.log(test2);
window.console.log(test3);
Not sure if your structure is expected to return an array of objects - or an array of values from each object. But the solution would be the same - use .map() on the original array to return the values (or objects) that you want.
const objArr = [
{id: 1, name: 'first item', value: 1},
{id: 2, name: 'second item', value: 2},
{id: 3, name: 'third item', value: 3}
];
const objIWant = 'value';
const result = objArr.map(item => item[objIWant]);
console.log(result);
// expected output: Array ["1", "2", "3"]
if its a nested object then same deal - use .map() on the original array to construct a new array of the desired objects.
const objArr = [
{"obj": {id: 1}, "obj": { id:1 } , "objIWant": { id:1 }},
{"obj": {id: 1}, "obj": { id:1 } , "objIWant": { id:2 }},
{"obj": {id: 1}, "obj": { id:1 } , "objIWant": { id:3 }}
];
const objIWant = 'objIWant';
const result = objArr.map(item => item[objIWant]);
console.log(result);
// expected output: Array [{"id": 1},{"id": 2},{"id": 3}]
Related
There are two array of objects and i want to filter two values by iterating differently to get two different id.
Here is the example
1st array : list_of_products: [ { text: "Shoes", value: 1},{text:"Clothing", value: 2},{text:"Foods", value: 3}]
2nd Array: list_of_names: [{ text: "jim" , value: 1},{text:"Sim", value: 2},{text:"Tim",value:3}]
Now, i want to get the ids by filtering out two arrays based on names like this
product_name: "Clothing", person_name:"Tim"
Then i want to store the ids like this
const newIds = { product_id: 2,name_id: 3}
This i have tried:
const newProduct_name = list_of_products.find(name => name.text === product_name);
const newName = list_of_names.find(name => name.text === person_name);
storing it into new object like this
const values = {product_id: newProduct_name.value ,name_id: newName.value}
How to do this by minimal use of variables and faster execution?
Creating Maps or objects using the lookup values as keys lets you iterate each of your source arrays once and then have o(1) searches rather than using find() to iterate each array many times
const products= [ { text: "Shoes", value: 1},{text:"Clothing", value: 2},{text:"Foods", value: 3}],
names= [{ text: "jim" , value: 1},{text:"Sim", value: 2},{text:"Tim",value:3}];
const createMap = (arr) => new Map(arr.map(o => [o.text, o.value])),
prodMap = createMap(products),
namesMap = createMap(names);
const data = [{
product_name: "Clothing",
person_name: "Tim"
}];
const res = data.map(o => {
return {
product_id: prodMap.get(o.product_name),
name_id: namesMap.get(o.person_name)
};
})
console.log(res)
I have one array and one object that contains array of ids (permission objects).
now i want to get the ids that are not present in the object can anyone help me with the logic?
id: [2,3,4]
object = [0:
Permission: {id: 2},
1: Permission: {id: 3}
]
result: [4]
Use filter(). Example:
var id = [2,3,4];
var object = [
{id: 2},
{id: 3}
];
objectIds = object.map(myObj => myObj.id);
idNotIn = id.filter(myId => !objectIds.includes(myId));
console.log('objectIds: '+ objectIds);
console.log('idNotIn: '+ idNotIn);
Or in a single line of code:
idNotIn = id.filter(myId => !object.map(myObj => myObj.id).includes(myId));
Consider having the following json
[
{'key1': { ... }},
{'key2': { ... }},
{'key3': { ... }}
]
I want to extract the keys for those objects in an elegant way, the following code is working, but it seems ugly to me.
let result = objects.map(o => Object.keys(o))[0]
the [0] at the end because the returned value is an array of array
You can use .concat() and .map() methods to get the desired result:
let data = [
{'key1': { }},
{'key2': { }},
{'key3': { }}
];
let result = [].concat(...data.map(Object.keys));
console.log(result);
References:
Array.prototype.concat()
Array.prototype.map()
Object.keys()
Spread Syntax
An array can only hold values, objects hold key/value pairs. Don't forget to use JSON.parse(json) before actually manipulating the data.
I'm guessing you need something along the lines of:
const list = [
{1: "one"},
{2: "two"},
{3: "three"}
];
I edited your JSON.
const data = [
{ 'key2': { }} ,
{'key1': { }},
{'key3': { }}
];
const result = [].concat.apply([], data.map(Object.keys));
console.log(result);
I have this (says it's Object A)
[{grade:1},{grade:2},{grade:3}] till 100th.
how to map this existing data (says its name is object B) into them?
[
{grade:1,name:'alice',address:{poscode:123},tel:324}
{grade:5,name:'wonder',address:{poscode:123},tel:1234223},
{grade:90,name:'james',address:{poscode:234},tel:324}]
]
Says grade 50, it doesn't match any of Object B, the final result should also have the name and address property, assign the value null to them to make the array consistent. I issue is what if there's other property in Object B if I loop using Object A?
If I understand the issue correctly, you can use Object A as your map source, then use Object.assign to copy individual properties from Object B as well as adding in some defaults:
const objA = [{grade:1},{grade:2},{grade:3}];
const objB = [
{grade:1,name:'alice',address:{poscode:123},tel:324},
{grade:5,name:'wonder',address:{poscode:123},tel:1234223},
{grade:90,name:'james',address:{poscode:234},tel:324}
];
const objC = objA.map(rootObject => Object.assign(
// A new object with some defaults
{ name: null, address: null, tel: null },
// The source object from objA
rootObject,
// The data object from objB, if any
objB.find(detail => detail.grade === rootObject.grade)
)
);
console.log(objC);
You can achieve that using convenient Array methods. See snippet below:
const a = [
{grade: 1},
{grade: 2},
{grade: 3},
{grade: 4},
{grade: 5},
{grade: 90},
{grade: 100}
];
const b = [
{grade:1,name:'alice',address:{poscode:123},tel:324},
{grade:5,name:'wonder',address:{poscode:123},tel:1234223},
{grade:90,name:'james',address:{poscode:234},tel:324}
];
let result = a.map(aItem => {
let match = b.find( bItem => aItem.grade === bItem.grade );
if(!match){
return Object.assign({}, aItem, { name: null, address: {}, tel: null });
} else {
return match;
}
});
console.log(result);
I created an immutable map (with Immutable-JS) from a list of objects:
var result = [{'id': 2}, {'id': 4}];
var map = Immutable.fromJS(result);
Now i want to get the object with id = 4.
Is there an easier way than this:
var object = map.filter(function(obj){
return obj.get('id') === 4
}).first();
Essentially, no: you're performing a list lookup by value, not by index, so it will always be a linear traversal.
An improvement would be to use find instead of filter:
var result = map.find(function(obj){return obj.get('id') === 4;});
The first thing to note is that you're not actually creating a map, you're creating a list:
var result = [{'id': 2}, {'id': 4}];
var map = Immutable.fromJS(result);
Immutable.Map.isMap(map); // false
Immutable.List.isList(map); // true
In order to create a map you can use a reviver argument in your toJS call (docs), but it's certainly not the most intuitive api, alternatively you can do something like:
// lets use letters rather than numbers as numbers get coerced to strings anyway
var result = [{'id': 'a'}, {'id': 'b'}];
var map = Immutable.Map(result.reduce(function(previous, current) {
previous[ current.id ] = current;
return previous;
}, {}));
Immutable.Map.isMap(map); // true
Now we have a proper Immutable.js map which has a get method
var item = Map.get('a'); // {id: 'a'}
It may be important to guarantee the order of the array. If that's the case:
Use an OrderedMap
Do a set method on the OrderedMap at each iteration of your source array
The example below uses "withMutations" for better performance.
var OrderedMap = Immutable.OrderedMap
// Get new OrderedMap
function getOm(arr) {
return OrderedMap().withMutations(map => {
arr.forEach(item => map.set(item.id, item))
})
}
// Source collection
var srcArray = [
{
id: 123,
value: 'foo'
},
{
id: 456,
value: 'bar'
}
]
var myOrderedMap = getOm(srcArray)
myOrderedMap.get(123)
// --> { id: 123, value: 'foo' }
myOrderedMap.toObject()
// --> { 123: {id: 123, value: 'foo'}, 456: {id: 456, value: 'bar'} }
myOrderedMap.toArray()
// --> [ {id: 123, value: 'foo'}, { id: 456, value: 'bar' } ]
When using fromJS for array, you'll get List not map. It will be better and easier if you create a map. The following code will convert the result into Immutable map.
const map = result.reduce((map, json) =>
map.set(json.id, Immutable.fromJS(json))
, Map());
Now, you can
map.get('2'); //{'id': 2}
Note, if the result has nested structure and if that has array, it will be a List with the above code.
With ES2015 syntax (and constants):
const result = map.find(o => o.get('id') === 4);
Is there already a way thats easier? I don't know. but you can write your own function. Something like this should work:
var myFunc = function(id){
var object = map.filter(function(obj){return obj.get('id') === id}).first();
return object;
}
Then you would just do:
var myObj = myFunc(4);