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])
Related
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;
})
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'm using an api that return this object:
{
"0155894402285712": { "type": "GBUserFieldText", "value": "A0242", "name": "Codice+tessera" },
"0155894402283800": { "type": "GBUserFieldText", "value": "LZZMRN55L53C003Z", "name": "Codice+Fiscale" }
}
I need to extract the value A0242 and LZZMRN55L53C003Z but the only things that I know are the name "Codice+tessera" and "Codice+fiscale". How can I read these values? Maybe my question is stupid but really I'm losing my brain today...
Thanks
You can try this:
const data = {
"0155894402285712": {
"type": "GBUserFieldText",
"value": "A0242",
"name": "Codice+tessera"
},
"0155894402283800": {
"type": "GBUserFieldText",
"value": "LZZMRN55L53C003Z",
"name": "Codice+Fiscale"
}
};
// get an array of all the values of this data.
const arrayOfValues = Object.values(data);
// filter this array in order to find the one which the name you want
const selectedObj = arrayOfValues.find(obj => obj.name === 'Codice+tessera');
// get the value of this object.
const selectedValue = selectedObj.value;
console.log(selectedValue);
// You can also make a function findValueOf(name):
const findValueOf = name =>
arrayOfValues.find(obj => obj.name === name) &&
arrayOfValues.find(obj => obj.name === name).value;
// and use it for example:
console.log(findValueOf('Codice+tessera')); // "A0242"
console.log(findValueOf('Codice+Fiscale')); // "LZZMRN55L53C003Z"
You can use Object.values and then access value key's value
let obj = {
"0155894402285712": { "type": "GBUserFieldText", "value": "A0242", "name": "Codice+tessera" },
"0155894402283800": { "type": "GBUserFieldText", "value": "LZZMRN55L53C003Z", "name": "Codice+Fiscale" }
}
Object.values(obj).forEach(({value})=>{
console.log(value)
})
You can use Object.values to convert the object into an array. Use map to loop and get the value
var obj = {"0155894402285712":{"type":"GBUserFieldText","value":"A0242","name":"Codice+tessera"},"0155894402283800":{"type":"GBUserFieldText","value":"LZZMRN55L53C003Z","name":"Codice+Fiscale"}}
var resut = Object.values(obj).map(o => o.value);
console.log(resut);
If you want to match the name and value, you can use reduce
var obj = {"0155894402285712":{"type":"GBUserFieldText","value":"A0242","name":"Codice+tessera"},"0155894402283800":{"type":"GBUserFieldText","value":"LZZMRN55L53C003Z","name":"Codice+Fiscale"}}
var resut = Object.values(obj).reduce((c, v) => Object.assign(c, {[v.name]: v.value}), {});
console.log(resut);
If you are looking to find A0242 from the value "Codice+tessera" that you have, you need something different than the other answers:
var data = {
"0155894402285712": { "type": "GBUserFieldText", "value": "A0242", "name": "Codice+tessera" },
"0155894402283800": { "type": "GBUserFieldText", "value": "LZZMRN55L53C003Z", "name": "Codice+Fiscale" }
}
const values = ["Codice+tessera", "Codice+fiscale"]
const results = values.map(v => Object.values(data).find(datum => datum.name === v)).map(v => v.value)
console.log(results) // [ "A0242", "LZZMRN55L53C003Z" ]
My target is if the id from digital_assets and products matches then get the value of URL fro digital_assets and ProductName from products object. I'm able to traverse through the object and get the values of digital_assets and products but need some help to compare these two objects based on IDs to get the value of URL and ProductName. Below is what I've done so far.
var data = [{
"digital_assets": [{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}]
}, {
"products": [{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},{
"id": ["BB002", "AA002"],
"ProductName": "PROD 555"
}]
}
];
$.each(data, function () {
var data = this;
//console.log(data);
$.each(data.digital_assets, function () {
var dAssets = this,
id = dAssets['id'];
// console.log(id);
});
$.each(data.products, function () {
var proData = this,
prod_id = proData['id'];
// console.log(prod_id);
$.each(prod_id, function () {
var arr_id = this;
console.log(arr_id);
});
});
});
Do I need to create new arrays and push the values into the new arrays? Then concat() these array to one. ? Bit lost any help will be appreciated.
Here is one way you can do this via Array.reduce, Array.includes, Object.entries and Array.forEach:
var data = [{ "digital_assets": [{ "id": "AA001", "url": "https://via.placeholder.com/150" }, { "id": "AA002", "url": "https://via.placeholder.com/150" } ] }, { "products": [{ "id": ["BB001", "AA001"], "ProductName": "PROD 485" }, { "id": ["BB002", "AA002"], "ProductName": "PROD 555" } ] } ]
const result = data.reduce((r,c) => {
Object.entries(c).forEach(([k,v]) =>
k == 'digital_assets'
? v.forEach(({id, url}) => r[id] = ({ id, url }))
: v.forEach(x => Object.keys(r).forEach(k => x.id.includes(k)
? r[k].ProductName = x.ProductName
: null))
)
return r
}, {})
console.log(Object.values(result))
You can use Array.prototype.find, Array.prototype.includes and Array.prototype.map to achieve this very gracefully.
let data = [
{
"digital_assets": [
{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},
{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}
]
},
{
"products": [
{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},
{
"id": ["BB002","AA002"],
"ProductName": "PROD 555"
}
]
}
];
// Find the 'digital_assets' array
let assets = data.find(d => d['digital_assets'])['digital_assets'];
// Find the 'products' array
let products = data.find(d => d['products'])['products'];
// Return an array of composed asset objects
let details = assets.map(a => {
return {
id : a.id,
url : a.url
name : products.find(p => p.id.includes(a.id)).ProductName
};
});
console.log(details);
changed answer to fit your needs:
var data = [
{
"digital_assets": [
{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},
{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}
]
},
{
"products": [
{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},
{
"id": ["BB002","AA002"],
"ProductName": "PROD 555"
}
]
}
]
let matchingIds = [];
let data_assetsObject = data.find(element => {
return Object.keys(element).includes("digital_assets")
})
let productsObject = data.find(element => {
return Object.keys(element).includes("products")
})
data_assetsObject["digital_assets"].forEach(da => {
productsObject["products"].forEach(product => {
if (product.id.includes(da.id)){
matchingIds.push({
url: da.url,
productName: product.ProductName
})
}
})
})
console.log(matchingIds);
working fiddle: https://jsfiddle.net/z2ak1fvs/3/
Hope that helped. If you dont want to use a new array, you could also store the respective data within the element you are looping through.
Edit:
I think i know why i got downvoted. My example works by making data an object, not an array. changed the snippet to show this more clearly.
Why is data an array anyway? Is there any reason for this or can you just transform it to an object?
Edit nr2:
changed the code to meet the expectations, as i understood them according to your comments. it now uses your data structure and no matter whats in data, you can now search for the objects containing the digital_assets / products property.
cheers
https://jsfiddle.net/2b1zutvx/
using map.
var myobj = data[0].digital_assets.map(function(x) {
return {
id: x.id,
url: x.url,
ProductName: data[1].products.filter(f => f.id.indexOf(x.id) > -1).map(m => m.ProductName)
};
});
I have the following response from a GET request to an API end point:
{
"success": true,
"data": {
"categories": [
{
"id": 1,
"label": "Default",
"url": "default",
"num_of_subs": 0
},
{
"id": 2,
"label": "Pet Grooming",
"url": "pet-grooming",
"num_of_subs": 2
},
],
}
}
Here is the fetch code:
const sendRegisterData = fetch('https://sg.cuzzey.com/api/listings/categories', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
})
.then((response) => response.text())
.then((responseText) => {
var response_final = JSON.parse(responseText);
if (response_final.success) {
this.setState({
categories: response_final.data.categories,
})
}
})
What I want to do, is to get the data from the categories and print them out as String and number (id and num_of_subs as number, label and url as String). Here is what I did:
const category_options = this.state.categories.map(category => {
return [<Text key={category.id} style={styles.smallTextBox}> {category.id} {'\n'}</Text>,
<Text key={category.label} style={styles.smallTextBox}> {category.label} {'\n'}</Text>,
<Text key={category.num_of_subs} style={styles.smallTextBox}> {category.num_of_subs} {'\n'}</Text>]
})
<ModalDropdown options={category_options} onSelect={(idx, label) => this.getCategory(idx, label)}>
<Text style={styles.smallTextBox}> {this.state.selected_category} </Text>
</ModalDropdown>
I used this code to get the value of id, label and num_of_subs:
getCategory = (idx, value) => {
this.setState({ category_id: value[0], selected_category: value[1], numSubs: value[2] })
}
When I print out category_id, selected_category and numSubs, the values are correct. However, they are object types and not String/number. I want to manipulate the values but I don't know how to convert them into String/number. I have tried using String(), Number(), parseInt(), JSON.parse(), toString() but none seems to work as they all result in "object" when I print out the typeof of the values.
Can I ask is there a way to solve this?
Your code is not working because you are not iterating through the array of objects. You are simply returning the object of arrays. This is why you cannot extract the value
var items = [{
"success": true,
"data": {
"categories": [{
"id": 1,
"label": "Default",
"url": "default",
"num_of_subs": 0
},
{
"id": 2,
"label": "Pet Grooming",
"url": "pet-grooming",
"num_of_subs": 2
},
],
}
}]
setState = [];
var catagories = items.map(x => x.data.categories);
catagories = catagories.reduceRight(x => x.cantact([]));
getCategory = (values) => {
for (let value of values) {
setState.push({
category_id: value.id,
selected_category: value.label,
numSubs: value.num_of_subs
})
}
}
var output = getCategory(catagories)
var results = setState.filter(x => x.numSubs > 0)
console.log(results);