I have an endpoint that returns the following object properties:
{
"id": "1",
"department": "sample",
"address": "sample",
"email": "sample#email.com",
"products": [
{
"id": "100",
"product_type": "A",
"product_category": "sample",
"category": "sample"
},
{
"id": "101",
"product_type": "A",
"product_category": "sample",
"category": "sample"
}
]
}
I'm doing like this on Angular
this.httpService.get<Product>(<my_endpoint>).pipe(map(response => response.data))
I need to remove all the properties product_type from the array of objects and keep the rest intact. I can't find if is possible to do this with only RxJs library filtering capabilities.
You can use RxJS pluck and map, as well as array map and object destructuring to remove the un-needed property.
this.httpService.get<Product>(<my_endpoint>).pipe(
pluck('data'),
map( data => {
const products = data.products.map( p => {
const {product_type, ...others} = p;
return {
...others
}
});
return {
...data,
products
}
})
)
Note: don't use delete on objects if you can avoid it (it mutates the object)
Inside your map function do this:
map((response) =>{
let data = response.data;
let products = data.products;
products =products.map((product) =>{
delete product['property1'];
return product; // without deleted properties;
})
data.products =products ;
return data;
})
Related
Given the following sample JSON (stringified from the corresponding JavaScript object), I need to extract this information:
Find the object in persons which has the reference = 2.
If a person with this reference was found, get the name of the person's parent element (here: "B").
In the end, I need to build a new object looking similar to this. This won't be problematic but I'm struggling with how to extract these objects from the source. I tried different approaches with find(), map(), flatMap() and filter() but none of them really worked.
{
companyName: "B",
person: {
"reference": 2,
"name": "Bob"
}
}
Source
{
"root": [
{
"companies": [
{
"name": "A",
"persons": [
{
"reference": 1,
"name": "Alex"
}
]
}
]
},
{
"companies": [
{
"name": "B",
"persons": [
{
"reference": 2,
"name": "Bob"
},
{
"reference": 3,
"name": "Charles"
}
]
}
]
}
]
}
If you're just interested in the name of the company you can find it using:
const reference = 2;
const company = data.root.flatMap(item => item.companies)
.find(company => company.persons.some(person => person.reference === reference));
const companyName = company?.name;
// or if you cannot use optional chaining
const companyName = (company || {}).name;
In data.root.flatMap(item => item.companies) we iterate through all items in root, for each item we select its companies property. Since we don't want a nested array we use flatMap() to flatten the result by 1 level. This leaves us with an array of companies.
After that we'll call find() on the companies array, since we are looking for a specific company name. The criteria of the company is that some() (1 or more) of the persons should match the provided reference. If no match is found null will be returned (from find()).
We then take the find() result (company) and navigate to the name via optional chaining ?.. This will return the name of the company if present, or undefined if company is null
You can use array.reduce here
let data = JSON.parse(`{
"root": [
{
"companies": [
{
"name": "A",
"persons": [
{
"reference": 1,
"name": "Alex"
}
]
}
]
},
{
"companies": [
{
"name": "B",
"persons": [
{
"reference": 2,
"name": "Bob"
},
{
"reference": 3,
"name": "Charles"
}
]
}
]
}
]
}`)
// GET ALL THE COMPANIES DATA
let companies = data.root.reduce(
(prevValue, currValue) => {
prevValue.push(...currValue.companies)
return prevValue
},
[]
)
// FIND AND CREATE EXPECTED RESULT SET
let results = companies.reduce(
(prevValue, currValue) => {
// loop inside a loop, mind it
let refPerson = currValue.persons.find((item)=> item.reference == 2)
if(refPerson){
prevValue.push({
companyName: currValue.name,
person: refPerson
})
}
return prevValue
},
[]
)
console.log(results)
I have a problem on an object inside of an array and I wanted to display only that as an array.
data1
const data1 = [
{
"id": "01",
"info": "fefef",
"sub": "hieei",
"details": {
"data": "fruits"
}
},
{
"id": "02",
"info": "fefef",
"sub": "hieei",
"details": {
"data": "things"
}
}
]
expected output
const final= [
{
"data": "fruits"
},
{
"data": "things"
}
]
Code
const final = data.map((data) => { ...data})
map over the array and return a new object using the details property. If you don't return a new object, your new array will still carry references to the objects in the original array. So if you change a value of a property in that original array, that change will be reflected in the new array too, and you probably don't want that to happen.
const data1=[{id:"01",info:"fefef",sub:"hieei",details:{data:"fruits"}},{id:"02",info:"fefef",sub:"hieei",details:{data:"things"}}];
// Make sure you return a copy of the
// details object otherwise if you change the details
// of the original objects in the array
// the new mapped array will carry those object changes
// because the array objects will simply references to the old objects
const out = data1.map(obj => {
return { ...obj.details };
});
console.log(out);
Map through the array and extract its details property:
const data1 = [
{
"id": "01",
"info": "fefef",
"sub": "hieei",
"details": {
"data": "fruits"
}
},
{
"id": "02",
"info": "fefef",
"sub": "hieei",
"details": {
"data": "things"
}
}
]
const res = data1.map(e => e.details)
console.log(res)
Using map and destructuring will simplify.
const data1 = [
{
id: "01",
info: "fefef",
sub: "hieei",
details: {
data: "fruits",
},
},
{
id: "02",
info: "fefef",
sub: "hieei",
details: {
data: "things",
},
},
];
const res = data1.map(({ details: { data } }) => ({ data }));
console.log(res);
// if you just need the details object
const res2 = data1.map(({ details }) => details);
console.log(res2);
I am fetching a data from Laravel API this way
$inventory = Gifts::with('allocation')->get();
$response = [
'data' => $inventory->toArray(),
]
The output for the above looks like the image below in the console
This is what is inside the 0: {…}
{
"id": 1,
"name": "Bar 1",
"allocation": [
{
"id": 1,
"location_id": "1",
"qty": "2",
},
{
"id": 2,
"location_id": "4",
"qty": "32",
},
{
"id": 3,
"location_id": "7",
"qty": "12",
}
]
}
I'm trying to get an output like this
{
"isEditable": false,
"id": 1,
"name": "Bar 1",
"location1": "2"
"location4": "32"
"location7": "12"
}
It's an array that consists of 100+ entries like this and the allocation can be more or less or maybe empty as well
What I have done so far
const array = result.data(gift => ({ isEditable: false, ...gift }));
This adds "isEditable" field to the array.
You could use Array.prototype.map() to map the result array into a new one that only includes id, name, and the locationNN properties.
In the Array.prototype.map()'s callback:
Use the spread operator to separate the allocation property from the other properties of each array item (call it otherProps e.g.):
Spread the otherProps into a new object, inserting the isEditable property.
Map the allocation items into a key-value pair array, where the key is location_id appended to "location"; and the value is the qty property.
Use Object.fromEntries() on the key-value pair array to create an object, and spread that object into the outer object to be returned.
const output = result.map(r => {
const { allocation, ...otherProps } = r 1️⃣
return {
...otherProps, 2️⃣
isEditable: false,
...Object.fromEntries( 4️⃣
allocation.map(a => [`location${a.location_id}`, a.qty]) 3️⃣
)
}
})
demo
This solution uses reduce
const { allocation, ...rest } = gift
const processed = allocation.reduce((acc, loc, idx) => {
acc[`location${loc.location_id}`] = loc.qty
return acc
}, {})
const result = { ...rest, ...processed }
console.log(result)
what I have is like this
const employees = {
"0813562121": {
"city": "Melbourne",
"name": "Allison"
},
"8753452122": {
"city": "Melbourne",
"name": "Aria"
}
}
I need to make it into like this
const employees = [
{
"city": "Melbourne",
"name": "Allison",
"_id": "0813562121"
},
{
"city": "Melbourne",
"name": "Aria",
"_id": "8753452122"
}
]
i was thinking of using index of Object.keys(employees ) and Object.values(employees ), but I couldn't figure it out.
You're on the right track with Object.values, but I'd use Object.entries since it gives you both the property name and its value. Then it's a map:
const result = Object.entries(employees).map(([name, value]) => ({...value, _id: name}));
Live Example:
const employees = {
"0813562121": {
"city": "Melbourne",
"name": "Allison"
},
"8753452122": {
"city": "Melbourne",
"name": "Aria"
}
};
const result = Object.entries(employees).map(([name, value]) => ({...value, _id: name}));
console.log(result);
That uses:
Object.entries to get an array of [name, value] pairs from the object.
map to map the entries of that array into a different format
A concise-form arrow function for the map callback (more in a moment).
Destructuring in the map callback's parameter list to get the name and value in named parameters.
Spread syntax inside an object literal to spread out the own, enumerable properties of the objects into a new object, adding the _id property
Alternatively, you could modify the object rather than creating a new one, so that non-enumerable, or non-own properties are retained:
const result = Object.entries(employees).map(([name, value]) => {
value._id = name;
return value;
});
Live Example:
const employees = {
"0813562121": {
"city": "Melbourne",
"name": "Allison"
},
"8753452122": {
"city": "Melbourne",
"name": "Aria"
}
};
const result = Object.entries(employees).map(([name, value]) => {
value._id = name;
return value;
});
console.log(result);
The key thing there is that the same objects are in both employees and result, whereas with the first one we make a shallow copy.
try this
const employees = {
"0813562121": {
"city": "Melbourne",
"name": "Allison"
},
"8753452122": {
"city": "Melbourne",
"name": "Aria"
}
}
let jsonVariants =[];
Object.keys(employees).forEach(function(key) {
let obj =employees[key];
obj["_id"] =key;
jsonVariants.push(obj);
});
console.log(jsonVariants);
I have a function component that generates a linear chart in react based on an array of objects.
The data I'm pulling from the API looks like this:
{
"_id": "604face09b305032586fe235",
"username": "Demo",
"description": "0",
"duration": 0,
"date": "2021-03-15T18:52:10.749Z",
"createdAt": "2021-03-15T18:52:16.684Z",
"updatedAt": "2021-03-15T18:52:16.684Z",
"__v": 0
}
My code to generate the chart data is:
// GET Exercises
useEffect(() => {
axios.get("http://localhost:5000/exercises")
.then((result) => {
setIsLoaded(true);
setItems(result.data);
console.log(result.data)
})
.catch((error) => {
setIsLoaded(true);
setError(error);
})
}, [])
// chartdata
useEffect(() => {
const chartArray = items.map((item) => {
const container = {};
container.label = item.username;
container.data = [[stripDate(item.date), item.duration]]
return container;
});
setXp(chartArray);
}, [items])
However, the API could return multiple objects with "username": "Demo", what I want is that if the username value already exists in my chart data I want to update that container.data array with another array.
Current outcome:
{
"label": "Demo",
"data": [[15, "2021-03-15"]]
},
{
"label": "Demo",
"data": [[45, "2021-03-17"]]
}
What I want to achieve:
{
"label": "Demo",
"data": [[15, "2021-03-15"], [45, "2021-03-17"]]
}
Any help or guidance is appreciated.
You need to group your data based on the username value using array#reduce in an object accumulator. For repeated username push new data in the array. Then get the values from this accumulator using Object.values().
useEffect(() => {
const chartArray = Object.values(items.reduce((r, o) => {
r[o.username] = r[o.username] || { label: o.username, data: []};
r[o.username].data.push([o.duration, stripDate(o.date)]);
return r;
},{}));
setXp(chartArray);
}, [items])