How do I access nested objects properties in console.table()? - javascript

Lets say I have the following array of objects:
var data = [
{ id: 123, author: { id: 123 } },
{ id: 123, author: { id: 123 } }
];
How can I populate a column in console.table with the id property of the author object?
This does not seem to work: console.table(data, ['id', 'author.id']);

I'm not sure you can do it with nested properties.
You could use map to pull the data out into a better format and then console.table it:
const data = [
{ id: 123, author: { id: 123 } },
{ id: 123, author: { id: 123 } }
];
const out = data.map(obj => {
return {
id: obj.id,
authorId: obj.author.id
};
});
console.table(out);
Note: you cannot hide the index column.

Related

Filter object by property that starts with any of array elements

I have an object of contacts where I need to filter by the country code, for which I need to check if the ID of the contact (phone number) starts with any of the selected country codes array.
var countries = ['1', '91', '55', '972'];
var allContacts = [
{
id: '9123242135321',
name: 'Harun'
},
{
id: '905366365289',
name: 'Koray'
},
{
id: '135366365277',
name: 'Hayo'
},
{
id: '963923824212',
name: 'Bahaa'
},
{
id: '513324515689',
name: 'Hassan'
}];
I am looking for an efficient one-line solution without looping, so what I have tried before is:
allContacts.filter(c => c.id.some(l => countries.includes(l)));
But that worked if the id parameter is an array, and it searches the whole number instead of the beginning, what is the efficient way to filter the contacts which their id key startsWith any of the countries array values?
You need to iterate the countries and check with startsWith.
const
countries = ['1', '91', '55', '972'],
allContacts = [{ id: '9123242135321', name: 'Harun' }, { id: '905366365289', name: 'Koray' }, { id: '135366365277', name: 'Hayo' }, { id: '963923824212', name: 'Bahaa' }, { id: '513324515689', name: 'Hassan' }];
console.log(allContacts.filter(({ id }) => countries.some(c => id.startsWith(c))));

Why async.map returns multiple copies of array?

const async = require('async');
const arr = [
{ name: 'john', id: '1' },
{ name: 'Andrie', id: '2' }]
let collectArr = [];
let data = async.mapLimit(arr, 5, async function (input) {
collectArr.push({ name: input.name, id: input.id });
return collectArr;
})
data.then((result) =>{
console.log('success',result);
}).catch(e => console.log('err'));
So here i am providing array to async.mapLimit without callback and expecting promise here.
Expected Output :- [ { name: 'john', id: '1' }, { name: 'Andrie', id: '2' } ] ,
Got Result :-
[ [ { name: 'john', id: '1' }, { name: 'Andrie', id: '2' } ],
[ { name: 'john', id: '1' }, { name: 'Andrie', id: '2' } ] ]
So my question is why it is creating multiple copies of array, how to deal with this?
You are needlessly returning a sub array, and the same array reference each iteration, when all you want is to return the new object.
let data = async.mapLimit(arr, 5, async function (input) {
return { name: input.name, id: input.id };
});
Not sure why you need this to be async

ES6 array of hashes return unique array of hashes [duplicate]

This question already has answers here:
Create array of unique objects by property
(17 answers)
Closed 3 years ago.
I have an object that looks like this:
const posts = [
{ id: 0, user: { id: 5564, name: 'john'} },
{ id: 1, user: { id: 5564, name: 'john'} },
{ id: 2, user: { id: 5560, name: 'jane'} }
]
I need an array of the unique user hashes like this:
[
{ id: 5564, name: 'john'},
{ id: 5560, name: 'jane'}
]
I'm able to retrieve all the users attributes from the posts array by doing:
const postUsers = posts.map(post => post.user)
which returns:
[
{ id: 5564, name: 'john'},
{ id: 5564, name: 'john'},
{ id: 5560, name: 'jane'}
]
where user john is listed twice
I've been able to get my desired result by doing:
const unique = {};
const uniqueUsers = [];
for(var i in postUsers){
if(typeof(unique[postUsers[i].id]) == "undefined"){
uniqueUsers.push(postUsers[i]);
}
unique[postUsers[i].id] = 0;
};
uniqueUsers
but there must be a cleaner way.
I've also been able to return the unique ids of all users by doing:
var ids = posts.map(post => post.user.id)
var uniqueIds = Array.from(new Set(ids)).sort();
which returns
[5564, 5560]
not sure if that helps. this article helped me a little https://medium.com/tomincode/removing-array-duplicates-in-es6-551721c7e53f
You could take a Map and get only the unique users.
const
posts = [{ id: 0, user: { id: 5564, name: 'john'} }, { id: 1, user: { id: 5564, name: 'john'} }, { id: 2, user: { id: 5560, name: 'jane'} }],
unique = Array.from(posts.reduce((m, { user }) => m.set(user.id, user), new Map).values());
console.log(unique);
If you don't mind using lodash you can do something like
const users = _map.(posts, 'user') // To get the list of users
_.uniqBy(users, 'id') // to get the uniq ones
Put the objects directly in uniqueUsers, then use Object.values() at the end to convert the object to an array.
const posts = [
{ id: 0, user: { id: 5564, name: 'john'} },
{ id: 1, user: { id: 5564, name: 'john'} },
{ id: 2, user: { id: 5560, name: 'jane'} }
];
let uniqueUsers = {};
posts.forEach(({user}) => uniqueUsers[user.id] = user);
uniqueUsers = Object.values(uniqueUsers);
console.log(uniqueUsers);
Use reduce to reduce the array by checking if the value is already in the array. If it is already in the array, return the current state of the array, otherwise add the item to the array.
const posts = [
{ id: 0, user: { id: 5564, name: 'john'} },
{ id: 1, user: { id: 5564, name: 'john'} },
{ id: 2, user: { id: 5560, name: 'jane'} }
]
const r = posts.map(i => i.user).reduce((acc, itm) => {
return !acc.find(i => i.id == itm.id) && acc.concat(itm) || acc
}, [])
console.log(r)

How to get a subset of a Javascript object with nested properties?

I'm developing with Angular and I have the following Typescript array of objects:
docs = [
{
id: '1',
type: {
id: 1
desc: 'Category 1',
}
title: 'Foo",
date: '2018-06-21',
attachments: [
{ id: 51, filename: 'foo.pdf', title: 'Foo' },
{ id: 20, filename: 'bar.doc', title: 'Bar' }
]
},
{
id: '2',
type: {
id: 2
desc: 'Category 2',
}
title: 'Bar",
date: '2018-06-21',
attachments: [
{ id: 15, filename: 'foobar.xls', title: 'Foobar' },
{ id: 201, filename: 'example.doc', title: 'Example' }
]
}
]
I need to get only a subset of the properties, something like this:
docs = [
{
id: '1',
type: {
id: 1
desc: 'Category 1',
}
attachments: [
{ id: 51 },
{ id: 20 }
]
},
{
id: '2',
type: {
id: 2
desc: 'Category 2',
}
attachments: [
{ id: 15 },
{ id: 201 }
]
}
]
How can I achieve this?
Have I to create a parser or does exist any smart way (such as Lodash) to extract a lite version of the array?
var docs = [{"id":"1","type":{"id":1,"desc":"Category 1"},"title":"Foo","date":"2018-06-21","attachments":[{"id":51,"filename":"foo.pdf","title":"Foo"},{"id":20,"filename":"bar.doc","title":"Bar"}]},{"id":"2","type":{"id":2,"desc":"Category 2"},"title":"Bar","date":"2018-06-21","attachments":[{"id":15,"filename":"foobar.xls","title":"Foobar"},{"id":201,"filename":"example.doc","title":"Example"}]}];
const result = docs.map(({id,type,attachments})=>{
let doc={id,type};
doc.attachments=attachments.map(({id})=>({id}));
return doc;
});
console.log(result);
have a look at this. this works perfectly!
You can use array.map and object destructuring to extract only the wanted properties.
Also use JSON.parse and JSON.stringify to make a copy and avoid side effetcs.
docs2 = JSON.parse(JSON.stringify(docs)).map(
({id, type, attachements}) =>
({ id,
type,
attachements: attachements.map(({id}) => ({id})
})
)
You can use Array.map with object spreading, something like this:
const mapSubset = ({ id, type, attachments }) => {
return { id, type, attachments: attachments.map( {id} => id ) };
};
const subset = docs.map( mapSubset );
I was looking for a non-specific way to accomplish this or any other similar cases, so far I've thought of the following:
Have an IMapping<T> type, that defines the way to map each property.
Have an IMappingFunction<T> interface, that determines how to map a specific thing:
The following code demonstrates it:
type IMapping<T> = {
[P in keyof T]: IMapping<T[P]> | IMappingFunction<T[P]>;
}
interface IMappingFunction<T>{
(t: T): T | Partial<T>
}
class Person{
name: string;
lastName: string;
}
const obj: IMapping<Person> = {
name: s => s.toUpperCase(),
lastName: s => s
}
function map<T>(obj: T, mapping: IMapping<T>) {
return Object.keys(obj)
.map(prop => {
const propMapping = mapping[prop];
return {
key: prop,
value: typeof propMapping === 'function' ?
propMapping(obj[prop]) :
map(obj, propMapping)
};
})
.reduce((acc, prop) => ({...acc, [prop.key]: prop.value}), { });
}
console.log(map({ name: 'Name', lastName: 'LastName'}, obj));
For a runnable snippet check here
do you need to leave the original array intact? If not you can iterate through the list of objects using a for loop and use the 'delete' operator to delete the properties you no longer want.
For example:
var Employee = {
firstname: "Mohammed",
lastname: "Haddad"
}
delete Employee.firstname;
console.log(Employee);
// expected output: { lastname: "Haddad" }

Iterate through JavaScript objects to produce an array of objects

I have an array of objects. One of the objects looks like this:
obj1 = {
name: 'rich',
email: 'rich#test.com',
date: {
greg : {
name: 'greg',
id: 1234}
}
}
How can I iterate through this array of objects (called usersArray) and add it to another array of objects (called usersArrayObj) with each object containing the name of the user (e.g. rich) and the name of the other (e.g. greg)
so that my end result would look like the below:
obj1 = {
name: 'rich',
pairName: 'greg',
}
I have tried to use hasOwnProperty and so forth but they behaving a little bit funky...
You can map the array like this:
var myArray = [
{ name: 'rich', email: 'rich#test.com', date: { greg: { name: 'greg', id: 1234 } } },
{ name: 'foo', email: 'foo#test.com', date: { bar: { name: 'bar', id: 5678 } } }
];
var results = myArray.map(function(item) { // For each item in the array
return { // Return an object,
name: item.name, // Using the current item's name
pairName: Object.keys(item.date)[0] // And the first key found on `item.date`
};
});
console.log(results);
This solution uses ES6. Use Array.prototype.map() and extract the object (inside greg:) using Object.values() (the the browser's support in the link):
const arr = [{
name: 'rich',
email: 'rich#test.com',
date: {
greg: {
name: 'greg',
id: 1234
}
}
}];
const result = arr.map(({ name, date }) => ({
name,
pairName: Object.values(date)[0].name
}));
console.log(result);
You can use Array.prototype.map() to crate the new array
To select the first key inside the object data you can use Object.keys() that will return you an array of a given object's own enumerable properties. You can then select the first element [0]
var usersArray = [{
"name": 'rich',
"email": 'rich#test.com',
"date": {
"greg": {
"name": 'greg',
"id": 1234
}
}
}, {
"name": 'jason',
"email": 'jason#test.com',
"date": {
"mickael": {
"name": 'mickael',
"id": 5678
}
}
}];
var usersArrayObj = usersArray.map(function(user) {
return {
"name": user.name,
"pairName": Object.keys(user.date)[0]
}
});
console.log(usersArrayObj);
.as-console-wrapper { max-height: 100% !important; top: 0; }
for this case what you can use is Object.keys() JS function.
obj2= {
name:obj1.name,
pairName: Object.keys(obj1.date)[0]
}
var arr = [{
name: 'rich',
email: 'rich#test.com',
date: {
greg : {
name: 'greg',
id: 1234}
}
}]
var newArr = [];
for (var i = 0; i < arr.length; i++) newArr[i] = {
name: arr[i].name,
pairName: Object.keys(arr[i].date)[0]
};
JSON.stringify(newArr); // "[{"name":"rich","pairName":"greg"}]"

Categories

Resources