I need help with this code.
I working with "#angular/cli": "~12.0.5".
The createArray method receives an object and I want to transform the object to an array, but I have an error in 'userObj [key]'. I get the object (userObj) from Firebase through an http request and I can't change its structure.
This is the error message. -> Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'. No index signature with a parameter of type 'string' was found on type '{}'
Thanks!
const userObj = {
'SJKLDFAD903':{
id: '',
name: 'User 1'
},
'PLMKL-BAD89':{
id: '',
name: 'User 2'
},
'JHK34R-R903':{
id: '',
name: 'User 3'
}
}
export class UserModel{
id: string;
name: string;
}
private createArray(userObj){ /*(userObj: object)*/
const users: UserModel[] = [];
if (userObj == null) { return []; }
Object.keys(userObj).forEach(key => {
const user: UserModel = userObj[key];
user.id = key;
users.push(user);
});
return users;
}
Try this.
private createArray(userObj){ /*(userObj: object)*/
const users: UserModel[] = [];
if (userObj == null) { return []; }
for (const [key, object] of Object.entries(userObj)) {
const user: UserModel = object as UserModel;
user.id = key;
users.push(user);
}
return users;
}
yow broh.
use Object.values instead
const userObj = {
'SJKLDFAD903':{
id: '',
name: 'User 1'
},
'PLMKL-BAD89':{
id: '',
name: 'User 2'
},
'JHK34R-R903':{
id: '',
name: 'User 3'
}
}
export class UserModel{
id: string;
name: string;
}
private createArray(userObj): UserModel[] {
return Object.values(userObj)
}
const userObj = {
'SJKLDFAD903':{
id: '',
name: 'User 1'
},
'PLMKL-BAD89':{
id: '',
name: 'User 2'
},
'JHK34R-R903':{
id: '',
name: 'User 3'
}
}
function createArray(userObj) {
return Object.values(userObj)
}
console.log(createArray(userObj))
Related
I have two arrays that I would like to compare and return a respective value of the ones that match.
Taking the 'id' variable as a reference, I want to return all the matching values of fastFood, but only the 'name'.
My expected result is to return Five Guys and KFC, but instead, it returns the entire object.
let id = ['1234'];
let fastFood = [
{_id:'4391', name: "McDonalds"},
{_id:'7654', name: "Burger King"},
{_id:'8765', name: "Dominos"},
{_id:'1234', name: "Five Guys"},
{_id:'9876', name: "Subway"},
{_id:'1234', name: "KFC"}
];
const findFastFood = ids.filter((item) => {
if (item._id.indexOf(id) !== -1) {
return item.name;
}
});
console.log(findFastFood);
Does this help?
let id = ['1234'];
let fastFood = [{
_id: '4391',
name: "McDonalds"
},
{
_id: '7654',
name: "Burger King"
},
{
_id: '8765',
name: "Dominos"
},
{
_id: '1234',
name: "Five Guys"
},
{
_id: '9876',
name: "Subway"
},
{
_id: '1234',
name: "KFC"
}
];
const findFastFood = fastFood.filter((item) => {
if (id.indexOf(item._id) !== -1) {
return item.name
}
}).map(obj => obj.name);
console.log(findFastFood);
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
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" }
I'm using TypeScript for the back-end of a web app, and I've found the intersection types quite useful for making efficient SQL queries. Basically, if I have the following tables:
User
userId: number
userEmail: string
Post
postId: number
userId: number (FK)
postBody: string
I can end up with an intersection type (User & Post) that looks like this:
{
userId: number;
userEmail: string;
postId: number;
postBody: string;
}
This means I can use this type to represent the rows I get back from a joined select query.
The problem is that I have to then pull apart the data in the web server. I have to write iterative code to group them for every query, and this can get repetitive. Here's the kind of transformation I'm trying to get:
In:
[
{
userId: 1,
userEmail: 'user1#email.com',
postId: 1,
postBody: 'User 1\'s first post',
},
{
userId: 1,
userEmail: 'user1#email.com',
postId: 2,
postBody: 'User 1\'s second post',
},
{
userId: 2,
userEmail: 'user2#email.com',
postId: 3,
postBody: 'User 2\'s first post',
},
]
Out:
[
{
userId: 1,
userEmail: 'user1#email.com',
posts: [
{
postId: 1,
postBody: 'User 1\'s first post',
},
{
postId: 2,
postBody: 'User 1\'s second post',
}
],
},
{
userId: 2,
userEmail: 'User 2\'s email',
posts: [
{
postId: 3,
postBody: 'User 2\'s first post',
}
]
}
]
I'm trying to come up with a function I can use to do this dynamically, perhaps passing in the collection, an array of parent key names, and the name of the child collection. I ended up with an unsuccessful function with the following signature: function group(coll: Array<any>, parentKeys: Array<string>, childCollName: string): Array<any>;
I was wondering if anybody could help me out with implementing this.
So far, I've already tried using Lodash. However, its groupBy function doesn't seem to be able to tell that the subobjects are equal and it still gives me an array of three objects in this example.
How about trying something like below, going in loop and creating objects
var arry = [
{
userId: 1,
userEmail: 'user1#email.com',
postId: 1,
postBody: 'User 1\'s first post',
},
{
userId: 1,
userEmail: 'user1#email.com',
postId: 2,
postBody: 'User 1\'s second post',
},
{
userId: 2,
userEmail: 'user2#email.com',
postId: 3,
postBody: 'User 2\'s first post',
},
];
function createPost(obj) {
post = {};
post.postId = obj.postId;
post.postBody = obj.postBody;
return post;
}
function convert(array) {
var map = {};
for (var i = 0; i < array.length; i++) {
var currentObject = array[i];
if (!map[currentObject.userId]) {
obj = {}
obj.userId = currentObject.userId;
obj.userEmail = currentObject.userEmail;
obj.posts = [];
map[obj.userId] = obj;
}
obj.posts.push(createPost(currentObject));
}
var keys = Object.keys(map);
return keys.map(function (v) { return map[v]; });
}
var r = convert(arry)
console.log(r);
You can use Array.prototype.reduce() to achieve the goal.
var source =
[
{
userId: 1,
userEmail: 'user1#email.com',
postId: 1,
postBody: 'User 1\'s first post',
},
{
userId: 1,
userEmail: 'user1#email.com',
postId: 2,
postBody: 'User 1\'s second post',
},
{
userId: 2,
userEmail: 'user2#email.com',
postId: 3,
postBody: 'User 2\'s first post',
},
]
var grouped = source.reduce(function(v,k){
if (!v[k.userId]) {
v[k.userId]={};
}
var group = v[k.userId];
group.userId=k.userId;
group.userEmail=k.userEmail;
if(!group.posts){
group.posts=[];
}
group.posts.push({postId: k.postId,
postBody:k.postBody})
return v;
},{})
var dataArray = [];
for(var o in grouped) {
if (grouped.hasOwnProperty(o)) {
dataArray.push(grouped[o]);
}
}
console.log(JSON.stringify(dataArray,null, 2));
Here's another take with reduce, some and destructuring
DEMO
const grouped = [
{
userId: 1,
userEmail: 'user1#email.com',
postId: 1,
postBody: 'User 1\'s first post',
},
{
userId: 1,
userEmail: 'user1#email.com',
postId: 2,
postBody: 'User 1\'s second post',
},
{
userId: 2,
userEmail: 'user2#email.com',
postId: 3,
postBody: 'User 2\'s first post',
}
];
const sorted = grouped.reduce((acc, nxt) => {
const { userId, userEmail, ...rest } = nxt;
let index;
let user;
const accHasUser = acc.some((obj, i) => {
if (obj && obj.userId === userId) {
index = i;
return true;
}
return false;
});
if (!accHasUser) {
user = { userId, userEmail, posts: [rest] };
acc.push(user);
} else {
acc[index].posts.push(rest);
}
return acc;
}, []);
console.log(JSON.stringify(sorted));
I'm deleting invitations by passing their IDs to the back end, which works. However, my reducer is not working properly to re-render the new, filtered array of invitations. When I refresh the page, the deleted invitation is gone. What am I doing wrong?
The action:
export function deleteInvitation(id) {
const user = JSON.parse(localStorage.getItem('user'));
console.log('now deleting id ', id);
return function(dispatch) {
axios
.delete(`${ROOT_URL}/invitation/`, {
headers: { authorization: user.token },
params: { id: id }
})
.then(response => {
console.log(id);
dispatch({
type: DELETE_INVITATION,
id
});
});
};
}
The reducer:
export default function(state = {}, action) {
switch (action.type) {
case INVITATION_SUCCESS:
return { ...state, invited: true, error: {} };
case INVITATION_FAILURE:
return { ...state, invited: false, error: { invited: action.payload } };
case FETCH_INVITATIONS:
return { ...state, invitations: action.payload };
case DELETE_INVITATION:
return {
...state,
invitations: state.invitations.filter(_id => _id !== action.id)
};
default:
return state;
}
}
I'm making a guess about the structure of the invitations array...
In the reducer, the filter function appears to be incorrect. The action is passing an id property, which I'm guessing is a property of an invitation object. But the filter function is filtering objects from state.invitations where the object is the id. That is, the reducer is doing something like this:
const action = {id: 0}
const invitation = [{
_id: 0,
name: 'Name 0',
location: 'Location 0'
},
{
_id: 1,
name: 'Name 1',
location: 'Location 1'
},
{
_id: 2,
name: 'Name 2',
location: 'Location 2'
}
];
console.log(invitation.filter(_id => _id !== action.id));
which will return the full original array because the filter function is checking for the inequality of action.id (a number) to an invitation (an object). Basically:
{
_id: 0,
name: 'Name 0', !=== number
location: 'Location 0'
}
will return true for any num and/or any invitation object, so the filter function will return every item in state.invitations.
To correct this, check the invitation._id against the action.id, like this:
const action = {id: 0}
const invitation = [{
_id: 0,
name: 'Name 0',
location: 'Location 0'
},
{
_id: 1,
name: 'Name 1',
location: 'Location 1'
},
{
_id: 2,
name: 'Name 2',
location: 'Location 2'
}
];
console.log(invitation.filter(invitation => invitation._id !== action.id));