I have the following interface
interface Employee{name?:string;id?:string;role?:string;}
I Have a Response like this
{
"name": "John",
"id": "ID77777",
"role": "Engineer",
"bloodType": "O+ve",
"placeOfDeployment": "NY"
}
I want to extract only the member variables of Interface.So after i am done with the mapping i should get
{
"name": "John",
"id": "ID77777",
"role": "Engineer"
}
You can use lodash which has pick function or here's vanilla js with same result.
const res = {"name": "John","id": "ID77777","role": "Engineer","bloodType": "O+ve","placeOfDeployment": "NY"};
const user = ["name", "id", "role"].reduce((acc, key) => {
acc[key] = res[key];
return acc;
}, {})
Note: handle case where res has missing keys.
You can use object destructing
const response = {
"name": "John",
"id": "ID77777",
"role": "Engineer",
"bloodType": "O+ve",
"placeOfDeployment": "NY"
}
// this will extract name,id,role property from response
const {name,id,role} = response;
// create a new object and assign those properties
let obj = {
name,
id,
role
};
console.log(obj)
You can use ts-transformer-keys, which enables you to obtain keys of given type.
import { keys } from 'ts-transformer-keys';
const keysOfEmployee = keys<Employee>();
const response = {
"name": "John",
"id": "ID77777",
"role": "Engineer",
"bloodType": "O+ve",
"placeOfDeployment": "NY"
};
const result = {};
keysOfEmployee.forEach(k => result[k] = response[k]);
Related
How to free two objects and leave the keys only from the other?
My example:
const first = {
"name": "John",
"address": "London"
}
const second = {
"name": null,
"email": null
}
const expectedResult = { // address was removed, because does not exist in second2
"name": "John",
"email": null
}
const third = {...first, ...second}
if (expectedResult == third) {
console.log("ok");
} else {
console.log("wrong");
}
const first2 = {
"name": "John",
"email": "john#john.com",
"address": "London"
}
const second2 = {
"name": null,
"email": null
}
const expectedResult2 = { // address was removed, because does not exist in second2
"name": "John",
"email": "john#john.com",
}
const third2 = {...first2, ...second2}
if (expectedResult2 == third2) {
console.log("ok");
} else {
console.log("wrong");
}
If it's easier, then second and second2 can simply be a array (and not an object with nulls) that are to appear as a result.
So you want to loop over the second and apply the values from the first.
const first = {
"name": "John",
"address": "London"
}
const second = {
"name": null,
"email": null
}
const result = Object.entries(second).reduce((acc, [key, value]) => {
acc[key] = key in first ? first[key] : value;
return acc;
}, {});
console.log(result);
Make it into a function:
const cleanUp = (main, sub) => Object.entries(main).reduce((acc, [key, value]) => {
acc[key] = key in sub ? sub[key] : value;
return acc;
}, {});
const first = { "name": "John", "address": "London" };
const second = { "name": null, "email": null };
const first2 = { "name": "John", "email": "john#john.com", "address": "London" };
const second2 = { "name": null, "email": null };
const result = cleanUp(second, first);
const result2 = cleanUp(second2, first2);
console.log(result);
console.log(result2);
The issue comes from:
The null values. To prevent those, you should use a custom method, for example here the merge function.
They are not exactly the same object. To check them, I'm using JSON.stringify(). According to what you compare, maybe you will no longer need it.
function merge(obj1, obj2) {
answer = {}
for(key in obj1) {
if(answer[key] === undefined || answer[key] === null)
answer[key] = obj1[key];
}
for(key in obj2) {
if(answer[key] === undefined || answer[key] === null)
answer[key] = obj2[key];
}
return answer
}
const first = {
"name": "John",
"address": "London"
}
const second = {
"name": null,
"email": null
}
const expectedResult = { // address was removed, because does not exist in second2
"name": "John",
"address": "London",
"email": null
}
const third = merge(first, second);
if (JSON.stringify(expectedResult) == JSON.stringify(third)) {
console.log("ok");
} else {
console.log("wrong", expectedResult, third);
}
This array has the key to substitute with nested key of 'name'
const arr = ['status', 'user', ...] <-- This array contains key to be replaced with name
This is what my current response object is
[
{
"id": 11,
"location": "Mumbai",
"status": {
"name": "NEW"
},
"user": {
"name": "Rakesh"
}
}
]
How do I modify the above array of objects to this below
[
{
"id": 11,
"location": "Mumbai",
"status": "NEW",
"user": "Rakesh"
}
]
can try below code
const keys = ['status', 'user']
let arr = [
{
"id": 11,
"location": "Mumbai",
"status": {
"name": "NEW"
},
"user": {
"name": "Rakesh"
}
}
]
arr.map(a => keys.forEach(k => {
if(a[k] && a[k].name) a[k] = a[k].name
}));
console.log(arr);
I'd try this one:
const results = [
{
"id": 11,
"location": "Mumbai",
"status": {
"name": "NEW"
},
"user": {
"name": "Rakesh"
}
}, {
"id": 12,
"location": "Helsinki",
"status": {
"name": "NEW"
},
"user": {
"name": "Samuli"
}
}
];
const flattenObject = ([key, value]) => ((typeof value === 'object') ? {[key] : value[Object.keys(value)[0]]} : {[key]: value});
const reduceToSingleObject = (acc, b) => ({...acc, ...b});
const actualResults = results.map((result) => Object.entries(result).map(flattenObject).reduce(reduceToSingleObject));
console.log(actualResults);
Explanation:
flattenObject is a function to flatten structure of object inside object. This only takes the first prop (without knowing the name of the key). If you, for some reason, would need to flatten several key-values, then it'd need whole different kind of helper function to sort that out.
reduceToSingleObject is a function to put all the key-value pairs into a single object. This could have been done already in flattenObject function, but for the clarity, I separated it to a normal map - reduce pattern.
actualResults is the outcome where we go through all the entries of your original results.
I have an array of object called actors:
const actors = [{
"name": "John Doe",
"rating": 1234,
"alternative_name": null,
"objectID": "551486300"
},
{
"name": "Jane Doe",
"rating": 4321,
"alternative_name": "Monica Anna Maria Bellucci",
"objectID": "551486310"
}];
I specifically want to get the name and the ratings of the actors.
I tried getting it by making a function called actorNameRating, but my code does not work.
const nameAndRating = function() {
const actorName = nameAndRating.filter(name);
return actorName;
const actorRating = nameAndRating.filter(rating);
return actorRating;
};
You can do by map a function and return only name and rating:
const actors = [{
"name": "John Doe",
"rating": 1234,
"alternative_name": null,
"objectID": "551486300"
},
{
"name": "Jane Doe",
"rating": 4321,
"alternative_name": "Monica Anna Maria Bellucci",
"objectID": "551486310"
}];
const nameAndRating = function() {
return actors.map(actor => ({
name : actor.name,
rating : actor.rating
}))
};
console.log(nameAndRating())
any thing after the return will not be executed you can return both values as one string then separate it
for example :
const nameAndRating = function() {
const actorName = nameAndRating.filter(name);
const actorRating = nameAndRating.filter(rating);
return actorName+","+actorRating;
};
or any other way you find better for you to use
I want to take a list of users and categorize them in a new array to be rendered by my app.
What I am given:
OnlineList = [
{
"Role": "Adjuster",
"AccountId": "4",
"UserId": "1e72d58e",
"DisplayName": "Big Bob",
},
{
"Role": "Adviser",
"AccountId": "5",
"UserId": "a0daba73",
"DisplayName": "Sassy Sally",
}
];
What result I want:
OnlineUsers = {
"Dealership": [
{
"Role": "Adviser",
"AccountId": "Dealership",
"UserId": "a0daba73",
"DisplayName": "Sassy Sally",
}
],
"ClaimsCo": [
{
"Role": "Adjuster",
"AccountId": "ClaimsCo",
"UserId": "1e72d58e",
"DisplayName": "Big Bob",
}
]
}
Result I get:
OnlineUsers = {
"5": [ <----------- Problem
{
"Role": "Adviser",
"AccountId": "5", <----------- Problem
"UserId": "a0daba73",
"DisplayName": "Sassy Sally",
}
],
"ClaimsCo": [
{
"Role": "Adjuster",
"AccountId": "Dealership",
"UserId": "1e72d58e",
"DisplayName": "Big Bob",
}
]
}
Here is a JFiddle I set up replicating the problem: http://jsfiddle.net/vc4mjwx3/20/
My code:
// loaded from API Request into array
var OnlineList = [];
// Sorted and ordered for display
var OnlineUsers = [];
OnlineList = [
{
"Role": "Adjuster",
"AccountId": "4",
"UserId": "1e72d58e",
"DisplayName": "Big Bob",
},
{
"Role": "Adviser",
"AccountId": "5",
"UserId": "a0daba73",
"DisplayName": "Sassy Sally",
}
];
// GroupBy function: https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects/43215522
let groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
// Simulates a get by Id API service
let accountService = (id) => {
if (id == 4) {
return "ClaimsCo."
}
else {
return "Dealership"
}
}
// pass in AccountId
let getAccountName = function(int) {
var accountName = "";
//get AccountName from Id
accountName = accountService(int);
for(var x=0; x < OnlineList.length; x++){
// check for AccountId
if(OnlineList[x].hasOwnProperty('AccountId')){
// Set AccountId value to AccountName
OnlineList[x].AccountId = accountName;
// Group results and set to OnlineUsers array
OnlineUsers = groupBy(OnlineList, 'AccountId');
break;
}
}
};
// Go into first element of array and get AccountId value
var id = _.get(OnlineList[0], "AccountId");
// Convert value to int
var int = parseInt(id,10);
// Pass into function that gets AccountName from AccountId and replaces AccountId in that element of OnlineList array
getAccountName(int);
//result
console.log(OnlineUsers);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Overall I want my code to function like this:
Iterate over each element in the OnlineList
For that element, grab the AccountId value
Pass that AccountId value into a service that will return an AccountName
Replace the AccountId of that element with the AccountName
repeat for all other elements in OnlineList array
After all AccountId/AccountName are handled, use GroupBy to group all elements of the OnlineList array by AccountId property and set them to a new array called OnlineUsers.
The question has been answered but I have a different solution I would like to share.
I recently created a library that does array categorization in JavaScript, called categorize.
Here is what would be the solution using it:
const { categorize } = require("categorize");
const onlineList = [
{
"Role": "Adjuster",
"AccountId": "4",
"UserId": "1e72d58e",
"DisplayName": "Big Bob",
},
{
"Role": "Adviser",
"AccountId": "5",
"UserId": "a0daba73",
"DisplayName": "Sassy Sally",
}
];
const categories = [
{ name: "Dealership", filter: ({ AccountId }) => AccountId === "4" },
{ name: "ClaimsCo", filter: ({ AccountId }) => AccountId === "5" },
];
const onlineUsers = categorize(onlineList, categories);
The onlineUsers variable will contain this object:
{
"Dealership": [
{
"Role": "Adjuster",
"AccountId": "4",
"UserId": "1e72d58e",
"DisplayName": "Big Bob"
}
],
"ClaimsCo": [
{
"Role": "Adviser",
"AccountId": "5",
"UserId": "a0daba73",
"DisplayName": "Sassy Sally"
}
]
}
// loaded from API Request into array
var OnlineList = [];
// Sorted and ordered for display
var OnlineUsers = [];
OnlineList = [{
"Role": "Adjuster",
"AccountId": "4",
"UserId": "1e72d58e",
"DisplayName": "Big Bob",
},
{
"Role": "Adviser",
"AccountId": "5",
"UserId": "a0daba73",
"DisplayName": "Sassy Sally",
}
];
// GroupBy function: https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects/43215522
let groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
// Simulates a get by Id API service
let accountService = (id) => {
if (id == 4) {
return "ClaimsCo."
} else {
return "Dealership"
}
}
// pass in AccountId
let getAccountName = function(int, element) {
var accountName = "";
//get AccountName from Id
accountName = accountService(int);
// check for AccountId
if (OnlineList[element].hasOwnProperty('AccountId')) {
// Set AccountId value to AccountName
OnlineList[element].AccountId = accountName;
// Group results and set to OnlineUsers array
OnlineUsers = groupBy(OnlineList, 'AccountId');
}
};
for (var x = 0; x < OnlineList.length; x++) {
var id = _.get(OnlineList[x], "AccountId");
var int = parseInt(id, 10);
getAccountName(int, x);
}
// Go into first element of array and get AccountId value
//result
console.log(OnlineUsers);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
I had to pass the count from my for loop into my getAccountName function. Now it works as it should. Hope this helps somebody.
You need to map and replace AccountId number with the name, and then group by the name. I use _.flow() to create a pipeline:
const { flow, partialRight: pr, map, groupBy } = _;
// Simulates a get by Id API service
const accountService = (id) => id === 4 ? "ClaimsCo." : "Dealership";
const fn = flow(
pr(map, o => ({ ...o, AccountId: accountService(+o.AccountId) })), // replace AccountId with name the + operator converts to number
pr(groupBy, 'AccountId'), // group by the new AccountId
)
const OnlineList = [{"Role":"Adjuster","AccountId":"4","UserId":"1e72d58e","DisplayName":"Big Bob"},{"Role":"Adviser","AccountId":"5","UserId":"a0daba73","DisplayName":"Sassy Sally"}];
//result
const OnlineUsers = fn(OnlineList);
console.log(OnlineUsers);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
And the terser version using lodash/fp:
const { flow, map, groupBy } = _;
// Simulates a get by Id API service
const accountService = (id) => id === 4 ? "ClaimsCo." : "Dealership";
const fn = flow(
map(o => ({ ...o, AccountId: accountService(+o.AccountId) })), // replace AccountId with name the + operator converts to number
groupBy('AccountId'), // group by the new AccountId
)
const OnlineList = [{"Role":"Adjuster","AccountId":"4","UserId":"1e72d58e","DisplayName":"Big Bob"},{"Role":"Adviser","AccountId":"5","UserId":"a0daba73","DisplayName":"Sassy Sally"}];
//result
const OnlineUsers = fn(OnlineList);
console.log(OnlineUsers);
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
I have this object structure:
"users": {
"1": {
"id": 1,
"name": "John",
"email": "john#doe.com",
"supplier_id": 1,
"supplier_name": [
"Supplier1"
],
"supplier_code": "SUP001",
"count": "21"
}
}
I'd like to change it so it appears like this:
"users": {
"1": {
"id": 1,
"name": "John",
"email": "john#doe.com",
"suppliers":[
{
"supplier_id": 1,
"supplier_name": [
"Supplier1"
]
}
],
"supplier_code": "SUP001",
"count": "21"
}
}
I tried this hoping it would work:
const group = accumulator[item.id];
group.suppliers = [];
group.suppliers = group.suppliers.push(item.supplier_name, item.supplier_id, item.supplier_code);
return accumulator;
Unfortunately that just seems to give me a count of the objects pushed into suppliers, suppliers isn't an array and supplier_id, supplier_name and supplier_code are still visible outside of suppliers:
"users": {
"1": {
"id": 1,
"name": "John",
"email": "john#doe.com",
"supplier_id": 1,
"supplier_name": [
"Supplier1"
],
"supplier_code": "SUP001",
"count": "21",
"suppliers: 3
}
}
How do I change it to the format I want?
You could use es6 Destructuring assignment, Object.values es2017 (or Object.keys instead).
If you assume that users contains more then one user you could use reduce.
In the example below original object won't be mutated.
Hope it helps
const original = {
"users": {
"1": {
"id": 1,
"name": "John",
"email": "john#doe.com",
"supplier_id": 1,
"supplier_name": [
"Supplier1"
],
"supplier_code": "SUP001",
"count": "21"
}
}
};
const { users } = original;
const reshaped = Object.values(users).reduce((acc, { id, supplier_id, supplier_name, ...rest }) => {
acc[id] = {
...rest,
suppliers: [{
supplier_id,
supplier_name: [supplier_name]
}]
};
return acc;
}, {});
console.log(reshaped);
You need to use an object to push into the suppliers array. Also, delete the old keys which are not needed.
Edit - You can directly create an array of 1 object. Thanks #Adam
const group = accumulator[item.id];
group.suppliers = [{
supplier_id: item.supplier_id,
supplier_name: item.supplier_name,
supplier_code: item.supplier_code
}];
delete group.supplier_id;
delete group.supplier_name;
delete group.supplier_code;
return accumulator;
Here's a quick and modern solution:
const parseUsers = (users) => {
let parsedUsers = {};
for (key in users) {
const user = users[key];
// destructuring (or extracting) the relevant keys from the . user object, keeping everything else under 'rest'
const { supplier_id, supplier_name, ...rest } = user;
parsedUsers[key] = {
...rest, // spreading back our rest params
suppliers: [ // creating a new array and populating it with the keys which we previously extracted (along with their corresponding values)
supplier_id,
supplier_name
]
}
}
return parsedUsers;
}
usage: parseUsers(json.users)