Related
How to combine JSON objects in the same response that has the same key and value with javascript? This is my data for example:
{
"data": [
{
"name": "A",
"description": {
"location": "location1",
"floor": "floor1",
},
},
{
"name": "A",
"description": {
"location": "location2",
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
}
And turn it into this:
{
"data": [
{
"name": "A",
"description": {
"location": ["location1","location2"],
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
}
Basically I am someone who is new to learning javascript. Any help would be very helpful, thank you.
You can do:
const data = {data: [{name: 'A',description: {location: 'location1',floor: 'floor1',},},{name: 'A',description: {location: 'location2',floor: 'floor1',},},{name: 'B',description: {location: 'location3',floor: 'floor3',},},],}
const result = {
data: data.data.reduce((a, { name, description }) => {
const index = a.findIndex((d) => d.name === name)
if (index >= 0) {
let location = a[index].description.location
location = Array.isArray(location) ? location : [location]
a[index].description.location = [...location, description.location]
} else {
a.push({ name, description })
}
return a
}, []),
}
console.log(result)
const list = {
"data": [
{
"name": "A",
"description": {
"location": "location1",
"floor": "floor1",
},
},
{
"name": "A",
"description": {
"location": "location2",
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
};
const consolidatedData = [];
for (const ele of list.data) {
const isExist = consolidatedData.find(x => x.name === ele.name);
if (!isExist) {
consolidatedData.push({
...ele
})
} else {
const objectKey = consolidatedData.findIndex(x => x.name === ele.name);
if (objectKey > -1) {
const description = consolidatedData[objectKey].description;
const newDes = ele.description;
if (newDes.location !== description.location) {
const data = consolidatedData[objectKey].description;
const added = [data.location, ele.description.location];
delete consolidatedData[objectKey].description.location
consolidatedData[objectKey].description["location"] = added
}
if (newDes.floor !== description.floor){
const data = consolidatedData[objectKey].floor;
const added = [data.floor, ele.description.floor];
delete consolidatedData[objectKey].description.floor
consolidatedData[objectKey].description["floor"] = added
}
}
}
}
console.log(JSON.stringify(consolidatedData, null, 2));
Here is a solution that uses an intermediate bucket object. The desired result object is then constructed from the bucket object:
const input = { "data": [ { "name": "A", "description": { "location": "location1", "floor": "floor1", }, }, { "name": "A", "description": { "location": "location2", "floor": "floor1", }, }, { "name": "B", "description": { "location": "location3", "floor": "floor3", }, }, ] };
let buckets = input.data.reduce((acc, obj) => {
if(!acc[obj.name]) {
acc[obj.name] = {
locations: {},
floors: {}
};
}
acc[obj.name].locations[obj.description.location] = true;
acc[obj.name].floors[obj.description.floor] = true;
return acc;
}, {});
console.log('buckets: ', buckets);
let result = {
data: Object.keys(buckets).map(name => {
let locations = Object.keys(buckets[name].locations);
let floors = Object.keys(buckets[name].floors);
return {
name: name,
description: {
location: locations.length == 1 ? locations[0] : locations,
floor: floors.length == 1 ? floors[0] : floors
}
}
})
};
console.log('result:', result);
Notes:
buckets object:
is created using an array .reduce()
array .reduce() docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
locations and floors are collected using objects instead of arrays, this is to avoid duplicate names
result object:
is using Object.keys(buckets) to get the array of names
.map() transforms each name into the desired object
your unusual array or string value for location and floor is constructed with a conditional
I wanted to list all the products in the database and all the images, today each product can have several images and this way I did it, it returns 1 product object for each image
I tried to do this, but I didn't get what I expected as I said above
async getAllProductAndImages() {
const productsDatabase = await client.query(`
SELECT
products.*,
products_images.id AS imageId,
products_images.name AS imageName,
products_images.product_id AS productImgId
FROM products INNER JOIN products_images
ON products.id = products_images.product_id`)
const products = productsDatabase.rows.map(products => {
const urlImage = `${process.env.APP_API_URL}/files/${products.imagename}`
const productImage = new ProductImage(products.imagename, products.id)
productImage.id = products.imageid
productImage.url = urlImage
const product = new Product(
products.name,
products.description,
products.price,
products.amount
)
product.id = products.id
product.productsImages = productImage
return product
})
return products
}
productsDatabase.rows return
[
{
"id": "3f671bc1-5163-44c8-88c9-4430d45f1471",
"name": "a",
"description": "a",
"price": "10",
"amount": 5,
"imageid": "78eb77d4-bf5a-44c1-a37a-0a28eb0f85ad",
"imagename": "21bb52fa-9822-4732-88c4-8c00165185d6-sunrise-illustration-digital-art-uhdpaper.com-hd-4.1963.jpg"
},
{
"id": "3f671bc1-5163-44c8-88c9-4430d45f1471",
"name": "a",
"description": "a",
"price": "10",
"amount": 5,
"imageid": "2157284b-34fd-41a4-ac3e-aa4d3f46b883",
"imagename": "96afbbc7-c604-4cfd-b634-0f39a4f20601-starry_sky_boat_reflection_125803_1280x720.jpg"
}
]
return that I have using the code above
[
{
"id": "3f671bc1-5163-44c8-88c9-4430d45f1471",
"name": "a",
"description": "a",
"price": "10",
"amount": 5,
"productsImages": {
"id": "78eb77d4-bf5a-44c1-a37a-0a28eb0f85ad",
"name": "21bb52fa-9822-4732-88c4-8c00165185d6-sunrise-illustration-digital-art-uhdpaper.com-hd-4.1963.jpg",
"url": "http://localhost:3000/files/21bb52fa-9822-4732-88c4-8c00165185d6-sunrise-illustration-digital-art-uhdpaper.com-hd-4.1963.jpg",
"product_id": "3f671bc1-5163-44c8-88c9-4430d45f1471"
}
},
{
"id": "3f671bc1-5163-44c8-88c9-4430d45f1471",
"name": "a",
"description": "a",
"price": "10",
"amount": 5,
"productsImages": {
"id": "2157284b-34fd-41a4-ac3e-aa4d3f46b883",
"name": "96afbbc7-c604-4cfd-b634-0f39a4f20601-starry_sky_boat_reflection_125803_1280x720.jpg",
"url": "http://localhost:3000/files/96afbbc7-c604-4cfd-b634-0f39a4f20601-starry_sky_boat_reflection_125803_1280x720.jpg",
"product_id": "3f671bc1-5163-44c8-88c9-4430d45f1471"
}
]
this is the return I expect and maybe there will be more stuff inside the productImages array there in the future
[
{
"id": "3f671bc1-5163-44c8-88c9-4430d45f1471",
"name": "a",
"description": "a",
"price": "10",
"amount": 5,
"productImages": [
{
"url": "http://localhost:3000/files/21bb52fa-9822-4732-88c4-8c00165185d6-sunrise-illustration-digital-art-uhdpaper.com-hd-4.1963.jpg",
"url": "http://localhost:3000/files/96afbbc7-c604-4cfd-b634-0f39a4f20601-starry_sky_boat_reflection_125803_1280x720.jpg"
}
]
}
]
Here is the solution considering productsDatabase.rows as arr:
const arr = [
{
id: "3f671bc1-5163-44c8-88c9-4430d45f1471",
name: "a",
description: "a",
price: "10",
amount: 5,
imageid: "78eb77d4-bf5a-44c1-a37a-0a28eb0f85ad",
imagename:
"21bb52fa-9822-4732-88c4-8c00165185d6-sunrise-illustration-digital-art-uhdpaper.com-hd-4.1963.jpg",
},
{
id: "3f671bc1-5163-44c8-88c9-4430d45f1471",
name: "a",
description: "a",
price: "10",
amount: 5,
imageid: "2157284b-34fd-41a4-ac3e-aa4d3f46b883",
imagename:
"96afbbc7-c604-4cfd-b634-0f39a4f20601-starry_sky_boat_reflection_125803_1280x720.jpg",
},
];
const newArr = [];
arr.forEach(a => {
if (!newArr.find(na => na.id === a.id)) {
const data = arr.filter(i => i.id === a.id).map(j => {
return {
url: `${process.env.APP_API_URL ? process.env.APP_API_URL : 'http://localhost:3000/'}files/${j.imagename}`
}});
newArr.push({
id: a.id,
name: a.name,
description: a.description,
amount: a.amount,
productsImages: data,
})
}
});
console.log(newArr);
You can just process the array to build a nested structure, but it might be easier to start with a subquery:
async getAllProductAndImages() {
const {rows} = await client.query(`
SELECT products.*, (
SELECT json_agg(json_build_object(
'id', products_images.id,
'name', products_images.name
))
FROM products_images
WHERE products_images.product_id = products.id;
) AS images
FROM products;
`);
const products = rows.map(row => {
const product = new Product(
row.name,
row.description,
row.price,
row.amount
);
product.id = row.id;
product.productsImages = row.images.map(img => {
const productImage = new ProductImage(img.name, product.id);
productImage.id = img.id;
productImage.url = `${process.env.APP_API_URL}/files/${img.name}`;
return productImage;
});
return product;
});
return products
}
Javascript
I have a nested array of objects, I'm trying to filter the given array of objects using a property from the third level of its array property value. For example, from the below array I like to filter the entire array using the property ListId: 10
Example
let test = {
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":11,
"name":"string2",
"state":"BY"
},
{
"ListId":12,
"name":"string3",
"state":"BY"
}
]
}
]
},
{
"name":"header2",
"value":[
{
"id":"01",
"list":[
{
"ListId":100,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":111,
"name":"string2",
"state":"BY"
},
{
"ListId":121,
"name":"string3",
"state":"BY"
}
]
}
]
}
]
}
Filtervalue with ListId = 10
Expected output :
{
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
}
]
}
]
}
]
}
How can I use the filter method using javascript to get this expected result?
You can two it in two times :
First, filter the list arrays,
Secondly filter the groups array using the some method
let test= {
"test": true,
"group": [
{
"name": "header",
"value": [
{
"id": "0",
"list": [
{
"ListId": 10,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 11,
"name": "string2",
"state": "BY"
},
{
"ListId": 12,
"name": "string3",
"state": "BY"
}
]
}
]
},
{
"name": "header2",
"value": [
{
"id": "01",
"list": [
{
"ListId": 100,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 111,
"name": "string2",
"state": "BY"
},
{
"ListId": 121,
"name": "string3",
"state": "BY"
}
]
}
]
}
]
}
test.group.forEach(group => {
group.value.forEach(value => {
value.list = value.list.filter(list => list.ListId === 10)
})
})
test.group = test.group.filter(group => group.value.some(value => value.list.length > 0))
console.log(test)
Note : You should use plural names for you arrays, it helps understanding the data. For example lists not list for the array.
let z ={"group1": [
{
"name": "header",
"value": [
{
"id": 0,
"list": [
{
"ListId": 10,
"Name": "string1"
},
{
"ListId": 11,
"Name": "string2"
}
]
}
]
}
]}
// This function was written from understading that 'group1' is not a fixed property, but part of a dynamic list due to the number '1'
const getItemByListId = (list, listId) => {
const listKeys = Object.keys(list);
const selectedListKey = listKeys.find(key => {
const groupItems = list[key];
const selectedItem = groupItems.find(({ value: nestedItems }) => {
const selectedNestedItem = nestedItems.find(({ list }) => {
const selectedList = list.find(({ ListId }) => ListId === listId)
return selectedList;
});
return selectedNestedItem;
});
return selectedItem;
});
if (!selectedListKey) {
return null;
}
return list[selectedListKey];
};
console.log(getItemByListId(z, 10));
const array = [
{
"data": {
"qty": "5",
"toy": {
"id": 3,
},
"available": "yes",
}
},
{
"data": {
"qty": "5",
"toy": {
"id": 10,
},
"available": "no"
}
},
{
"data": {
"qty": "59",
"toy": {
"id": 10,
},
"available": "yes",
}
},
{
"data": {
"qty": "5",
"toy": {
"id": 3,
},
"available": "yes",
}
}
]
var result = [];
array.reduce(function(res, value) {
if (!res['data']['toy'] || !res['data']['toy']['data']) {
res['data'] = {...value['data'] };
result.push(res['data'])
}
if (res['data']['available'] === value['data']['available'] && res['data']['toy']['id'] === value['data']['toy']['id']) {
res['data']['qty'] = parseInt(res['data']['qty']) + parseInt(value['data'].qty)
}
return res;
}, {'data': {}});
console.log(result)
I am working on a js project and I need a bit of help here. From the array, How to get a new array that has qty as the sum of the other qty value which data.toy.id and available same. i.e. I want the below array. My code is not working as excepted. Changes to the same or new code are also fine. Thank you.
const array = [
{
"data": {
"qty": "10",
"toy": {
"id": 3,
},
"available": "yes",
}
},
{
"data": {
"qty": "5",
"toy": {
"id": 10,
},
"available": "no"
}
},
{
"data": {
"qty": "59",
"toy": {
"id": 10,
},
"available": "yes",
}
}
]
You group the array into an object, where the keys are concatenation of available and id properties and finally transform the object back to an array using Object.values.
const
array = [
{ data: { qty: "5", toy: { id: 3 }, available: "yes" } },
{ data: { qty: "5", toy: { id: 10 }, available: "no" } },
{ data: { qty: "59", toy: { id: 10 }, available: "yes" } },
{ data: { qty: "5", toy: { id: 3 }, available: "yes" } },
],
result = Object.values(
array.reduce((r, { data }) => {
const k = data.available + data.toy.id;
if (r[k]) {
r[k].data.qty = String(Number(r[k].data.qty) + Number(data.qty));
} else {
r[k] = { data };
}
return r;
}, {})
);
console.log(result);
I'd suggest using Array.reduce() to group by a key, which will be combined value of the toy id and the available property.
We'd create a map of all toys based on this key, summing the quantity for each.
Finally, we'll use Object.values() to convert back into an array.
const array = [ { "data": { "qty": "5", "toy": { "id": 3, }, "available": "yes", } }, { "data": { "qty": "5", "toy": { "id": 10, }, "available": "no" } }, { "data": { "qty": "59", "toy": { "id": 10, }, "available": "yes", } }, { "data": { "qty": "5", "toy": { "id": 3, }, "available": "yes", } } ];
const result = Object.values(array.reduce((acc, { data: { qty, toy, available } }) => {
const key = `${toy.id}-${available}`;
acc[key] = acc[key] || { data: { qty: 0, toy, available } };
acc[key].data.qty += Number(qty);
return acc;
}, {}))
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }
You can use Array#reduce() to create arrayHash object using as keys: ${c.data.toy.id}-${c.data.available}
Code:
const array = [{data: {qty: '5',toy: {id: 3,},available: 'yes',},},{data: {qty: '5',toy: {id: 10,},available: 'no',},},{data: {qty: '59',toy: {id: 10,},available: 'yes',},},{data: {qty: '5',toy: {id: 3,},available: 'yes',},},]
const arrayHash = array.reduce((a, { data }) => {
const key = `${data.toy.id}-${data.available}`
a[key] = a[key] || { data: { ...data, qty: 0 } }
a[key].data.qty = (+a[key].data.qty + +data.qty).toString();
return a
}, {})
const result = Object.values(arrayHash)
console.log(result)
I'd use just reduce
const a1 = [
{
"data": {
"qty": "5",
"toy": {
"id": 3,
},
"available": "yes",
}
},
{
"data": {
"qty": "5",
"toy": {
"id": 10,
},
"available": "no"
}
},
{
"data": {
"qty": "59",
"toy": {
"id": 10,
},
"available": "yes",
}
},
{
"data": {
"qty": "5",
"toy": {
"id": 3,
},
"available": "yes",
}
}
]
const a2 = a1.reduce((acc, it) => {
let found = acc.find(
dp => dp.data.toy.id === it.data.toy.id && dp.data.available === it.data.available
)
if(found){
found.data.qty = ( Number(found.data.qty) + Number(it.data.qty) ).toString()
}
else acc.push(it)
return acc
}, [])
console.log(JSON.stringify(a2, null,2))
Hi I am getting data from API but I want my data in different format so that I can pass later into a function. I want to change the names of keys into a different one becasuse I have created a chart and it only draws if I send it data in certain way
This is what I am getting from API
data = {
"status": "success",
"from": "DB",
"indice": "KSE100",
"data": [
{
"stock_sector_name": "Tc",
"sector_score": "0828",
"stocks": [
{
"stock_symbol": "TRG",
"stock_score": 44
},
{
"stock_symbol": "SYS",
"stock_score": 33
}
]
},
{
"stock_sector_name": "OIL",
"sector_score": "0828",
"stocks": [
{
"stock_symbol": "FFS",
"stock_score": 44
},
{
"stock_symbol": "SMS",
"stock_score": 33
}
]
},
]
}
But I want my data to look like this like this
data = {
"name": "KSE100",
"children": [
{
"name": "A",
'points': -9,
"children": [
{
"stock_title": "A",
"value": 12,
},
{
"stock_title": "B",
"value": 4,
},
]
},
{
"name": "B",
'points': 20,
"children": [
{
"stock_title": "A",
"value": 12,
},
{
"name": "B",
"value": 4,
},
]
},
]
}
Like I want to replace
stock_sector_name = name
sector_score = value
stocks = children
stock_symbol = name
stock_score = value
I have been trying this for so much time but sill could not figured it out
function convert(d){
return {
name : d.indice,
children : d.data.map(y=>{
return {
name : y.stock_sector_name,
points : y.sector_score,
children : y.stocks.map(z=>{
return {
stock_title: z.stock_symbol,
value : z.stock_score
}
})
}
})
}
}
You can do something like this
const data = {
"status": "success",
"from": "DB",
"indice": "KSE100",
"data": [{
"stock_sector_name": "Tc",
"sector_score": "0828",
"stocks": [{
"stock_symbol": "TRG",
"stock_score": 44
},
{
"stock_symbol": "SYS",
"stock_score": 33
}
]
},
{
"stock_sector_name": "OIL",
"sector_score": "0828",
"stocks": [{
"stock_symbol": "FFS",
"stock_score": 44
},
{
"stock_symbol": "SMS",
"stock_score": 33
}
]
},
]
}
const data2 = {
"name": "KSE100",
"children": [{
"name": "A",
'points': -9,
"children": [{
"stock_title": "A",
"value": 12,
},
{
"stock_title": "B",
"value": 4,
},
]
},
{
"name": "B",
'points': 20,
"children": [{
"stock_title": "A",
"value": 12,
},
{
"name": "B",
"value": 4,
},
]
},
]
}
//stock_sector_name = name
//sector_score = value
//stocks = children
//stock_symbol = stock_title
//stock_score = value
const keys = {
stock_sector_name: "name",
sector_score: "points",
stocks: "children",
stock_symbol: "stock_title",
stock_score: "value",
indice: "name",
//data: "children"
}
const rename = (value) => {
if (!value || typeof value !== 'object') return value;
if (Array.isArray(value)) return value.map(rename);
return Object.fromEntries(Object
.entries(value)
.map(([k, v]) => [keys[k] || k, rename(v)])
);
}
renamedObj = rename(data);
console.log(renamedObj);