I have a JSON object which has multiple children and grandchildren I want to get the sum of grandchildren and show it with the children, similar get the sum of children and show it with the parent.
So in the end, the parent should display the sum of all children.
{
"id": 4,
"Nominal": "4",
"name": "Revenue",
"type": "Revenue",
"parent_id": 0,
"children": [
{
"id": 14,
"Nominal": "41",
"name": "Operational Revenue",
"parent_id": 4,
"transactions_sum_debit": null,
"transactions_sum_credit": null,
"children": [
{
"id": 46,
"Nominal": "4101",
"name": "Revenue of Products and services Sales",
"parent_id": 41,
"transactions_sum_debit": "1658.00",
"transactions_sum_credit": "3316.00",
"children": [],
"transactions": [
{
"id": 308,
"debit": null,
"credit": "64.00",
"first_level_id": 46
},
{
"id": 310,
"debit": null,
"credit": "765.00"
},
{
"id": 318,
"debit": null,
"credit": "64.00",
"first_level_id": 46,
"invoice_id": 20
},
{
"id": 320,
"debit": null,
"credit": "765.00",
"first_level_id": 46
},
{
"id": 340,
"debit": null,
"credit": "765.00",
"first_level_id": 46
},
{
"id": 466,
"debit": "64.00",
"credit": null,
"first_level_id": 46
},
{
"id": 468,
"debit": "765.00",
"credit": null,
"first_level_id": 46
}
]
}
],
"transactions": []
},
{
"id": 15,
"Nominal": "42",
"parent_id": 4,
"transactions_sum_debit": null,
"transactions_sum_credit": null,
"children": [
{
"id": 47,
"Nominal": "4201",
"parent_id": 42,
"transactions_sum_debit": null,
"transactions_sum_credit": "1520.00",
"children": [],
"transactions": [
{
"id": 304,
"debit": null,
"credit": "380.00",
"first_level_id": 47
},
{
"id": 334,
"debit": null,
"credit": "380.00",
"first_level_id": 47
}
]
}
],
"transactions": []
}
]
}
for example in the above JSON data I want to get the sum transactions_sum_debit from all the children and show it one level up. until the parent_id = 0
My View:
//get sum of all children in json
function sumOfChildrens(parent, id) {
let data = parent;
let ids = id;
let transactions_sum_credit = 0;
//call the function recursively until the last child
for (let i = 0; i < data.length; i++) {
if (data[i].id == ids) {
transactions_sum_credit += parseFloat(data[i].transactions_sum_credit);
}
if (data[i].children) {
transactions_sum_credit += sumOfChildrens(data[i].children, ids);
}
}
console.log(transactions_sum_credit);
return transactions_sum_credit;
}
$(document).ready(function() {
$.ajax({
headers: {
"Authorization": 'Bearer ' + sessionStorage.getItem('token')
},
type: "get",
url: "{{ URL::asset('api/reports/get-generalLedger') }}",
success: function(data) {
var data = data.data;
console.log(data);
$("#tablebody").empty();
data.map(parent => {
$("#tablebody").append(
`
<tr>
<td class="${parent.Nominal} id_${parent.id}">${parent.Nominal}</td>
<td class="${parent.Nominal} id_${parent.id}">${parent.name}</td>
<td class="${parent.Nominal} id_${parent.id}"></td>
<td class="${parent.Nominal} id_${parent.id}">${sumOfChildrens(parent,parent.id)}</td>
</tr>
`);
});
},
error: function(data) {
alert(data['message']);
console.log(data['message']);
},
});
});
Stackoverflow isn't meant for other people to write code for you, but rather to answer specific questions or help solve problems. Instead of showing more code, explain what you've tried, which behavior you saw vs the one you expected.
That being said, I think the following code snippet might help you clarify your question or even solve the problem on your own.
// for each first level child
data.children.map((item) => {
// for each next level child
item.children.map((item2) => {
// this is the list of transactions
console.log(item2.transactions);
let sum = 0;
// go over each transaction
item2.transactions.map((transaction) => {
// debit != null
if (transaction.debit) {
sum += parseFloat(transaction.debit);
}
});
// here you could add the sum to the parent
console.log(sum);
});
});
Try to edit this code so it works for you and come back if you have more questions.
Related
How can i make the cart_items like my expetation.. just it no more.. my problem just it :D
i just wanna make my cart_items like this.. hope you are can help me thanks. did I make the wrong method? and one more thing, i wanna make the qty inside the cart_items
this is my expectation
"cart": [
{
"id": 1,
"date": "12/10/2020",
"store": {
"id": 1,
"name": "Dirumah Aja",
"promo": 1
},
"cart_items": [
{
"id": 1,
"product": {
"id": 1,
"name": "Bakso Urat",
"price": 10000,
"promo": {
"nama": "promo"
}
},
"qty": 5
}
]
}
]
and this is what I got
"cart": [
{
"cart_items": {
"name": "Steak Sapi Impor",
"price": "38000",
"stock": "4",
"image": "https://firebasestorage.googleapis.com/v0/b/francise-fb70a.appspot.com/o/steak.jpg?alt=media&token=46e0d769-96d3-440f-8edb-5fce2481ace0",
"promo": 3,
"id": 8,
"qty": 1
},
"store": {
"name": "Amanda Foods Store",
"email": "amanda#food.com",
"store_image": "https://firebasestorage.googleapis.com/v0/b/francise-fb70a.appspot.com/o/full_hd_retina.jpeg?alt=media&token=3e602e86-661b-48ee-9e9c-af9f94a170d1",
"product": [
5,
7,
8,
2
],
"store_promo": 1,
"location": {
"street_name": "Jl. Kebon Gedang II B",
"province": "Jawa Barat",
"city": "Bandung",
"post_code": "40285"
},
"id": 1
},
"date_order": "Nov 03 2020 08:48:03",
"id": 2
}
]
This is my data
data() {
return {
promo_id: [],
promo_partner: [],
products: {},
qty: 1,
cart_items: [
{}
]
};
and this is my method
addToCart() {
const date = (new Date()).toString().split(' ').splice(1,4).join(' ')
this.products.cart_items = this.product;
this.products.cart_items.qty = this.qty;
this.products.store = this.partner;
this.products.date_order = date;
console.log(this.cart_items)
axios
.post("http://localhost:3000/cart/", this.products)
.then(() => {
swal("Belanja Berhasil!", {
icon: "success",
});
})
.catch((error) => console.log(error));
}
}
You need to use .push() to add items to an array. You're replacing the array with this.product.
if (!this.products.cart_items) { // initialize cart_items if necessary
this.products.cart_items = [];
}
this.products.cart_items.push({id: this.product.id, product: this.product, qty: this.qty});
These nested for loops loop through JSON object containing product categories and subcategories. It loops through these sending a URL parameter to a function to scrape a website according to the parameter. I cant find a way to add the returned arrays containing scraped data to the JSON object (according to its place in the nested loop) without having to create an empty array first and then use .push to populate it, thus duplicating the array brackets. The function returning the scraped data already add the data to an array, so I'm not sure how to go about this.
The following loops add the correct data to the JSON object, however the array brackets are tripled.
for (let i=0; i<obj.length; i++) {
let subcats = obj[i].subcategories;
for(let n=0; n<subcats.length; n++) {
if(!subcats.facetValueData) {
subcats[n].code.replace(/\s/g, '')
let productDataSub = []
subcats[n].productData = productDataSub
subcats[n].productData.push(await scrapeData(obj[i].subcategories[n].code))
} else {
let subcatsFinal = subcats[n].facetValueData
for(let p=0; p<subcatsFinal.length; p++) {
subcatsFinal[p].code.replace(/\s/g, '')
let productData = []
subcatsFinal[p].productData = productData
subcatsFinal[p].productData.push(await scrapeData(obj[i].subcategories[n].facetValueData[p].code))
}
}
}
}
The following is the JSON data being looped, the productData=[] is an example of where the productData array should go, but it is not present when the data is being looped. It is what I'm trying to achieve, but with the data populated inside. The "code" value is the parameter which is appended to a url to scrape that pages data.
[
{
"id": 0,
"categoryName": "Beauty",
"subcategories": [
{
"count": 2688,
"code": "/beauty/skin-care",
"name": "Skincare",
"facetValueData": [
{
"count": 682,
"code": "/beauty/skin-care/lotion-serum-and-essence",
"name": "Lotion Serum & Essence",
"productData": []
},
{
"count": 497,
"code": "/beauty/skin-care/moisturiser-and-mist",
"name": "Moisturiser & Mist",
"productData": []
},
{
"count": 354,
"code": "/beauty/skin-care/cleanser-and-exfoliation",
"name": "Cleanser & Exfoliation",
"productData": []
},
{
"count": 345,
"code": "/beauty/skin-care/mask-and-treatment",
"name": "Mask & Treatment",
"productData": []
}
]
},
{
"count": 1549,
"code": "/beauty/makeup",
"name": "Makeup",
"facetValueData": [
{
"count": 653,
"code": "/beauty/makeup/face",
"name": "Face",
"productData": []
},
{
"count": 460,
"code": "/beauty/makeup/makeup-lips",
"name": "Lips",
"productData": []
},
{
"count": 337,
"code": "/beauty/makeup/eyes",
"name": "Eyes",
"productData": []
},
{
"count": 124,
"code": "/beauty/makeup/makeup-cheeks",
"name": "Cheeks",
"productData": []
}
]
}
]
},
{
"id": 1,
"categoryName": "Electronics",
"subcategories": [
{
"count": 526,
"code": "/electronics/audio-devices",
"name": "Audio",
"facetValueData": [
{
"count": 153,
"code": "/electronics/audio-devices/speakers",
"name": "Speakers",
"productData": []
},
{
"count": 145,
"code": "/electronics/audio-devices/earphones",
"name": "Earphones",
"productData": []
},
{
"count": 142,
"code": "/electronics/audio-devices/headphones",
"name": "Headphones",
"productData": []
},
{
"count": 51,
"code": "/electronics/audio-devices/true-wireless-and-airpods",
"name": "True Wireless & Airpods",
"productData": []
}
]
}
]
}
]
Not sure if all that necessary but here is the async function which scraped the pages and returns the arrays:
async function scrapeData(queryParam) {
let pageCounter = 0;
var product = []
var pagination;
try {
do {
var nextPageLink = `currentPage=${pageCounter}&query=::cagCollectionPoint:Departure+from+Singapore:cagCategory:${queryParam}`
var nextUrl = url.concat(nextPageLink)
const response = await axios({
method: "GET",
url: nextUrl,
withCredentials: true,
headers: headers
})
console.log(nextUrl)
product.push(response.data["products"])
pagination = response.data["pagination"]["totalPages"]
pageCounter++;
// console.log(response.data.currentQuery.query.value)
} while (pageCounter<=0)
return product;
} catch (error) {
console.error(error)
}
}
I want to delete items from my array where the price is lower than 20
This is my array:
[
{
"suggested_price": 50,
"suggested_price_floor": 0,
"name": "Itemname",
"image": "link",
"wear": null,
"color": "ffbb00",
"id": 6039365
},
{
"suggested_price": 50,
"suggested_price_floor": 0,
"name": "Itemname",
"image": "link",
"wear": null,
"color": "ffbb00",
"id": 6039365
}
]
and if the suggested_price is lower than 20, i will delete that out of my array list
I tried to find how on the internet but couldn't find how :/
Only find sorting array by price
You want to use filter.
const items = [{
suggested_price: 19,
suggested_price_floor: 0,
name: 'Itemname',
image: 'link',
wear: null,
color: 'ffbb00',
id: 6039365
},
{
suggested_price: 50,
suggested_price_floor: 0,
name: 'Itemname',
image: 'link',
wear: null,
color: 'ffbb00',
id: 6039365
}
];
const reducedItems = items.filter(item => (item.suggested_price > 20));
console.log(reducedItems)
;
you can use array.filter, which will create a new array with the condition passed on the filter function
var res = [
{
"suggested_price": 50,
"suggested_price_floor": 0,
"name": "Itemname",
"image": "link",
"wear": null,
"color": "ffbb00",
"id": 6039365
},
{
"suggested_price": 6,
"suggested_price_floor": 0,
"name": "Itemname",
"image": "link",
"wear": null,
"color": "ffbb00",
"id": 6039365
},
{
"suggested_price": 15,
"suggested_price_floor": 0,
"name": "Itemname",
"image": "link",
"wear": null,
"color": "ffbb00",
"id": 6039365
},
{
"suggested_price": 34,
"suggested_price_floor": 0,
"name": "Itemname",
"image": "link",
"wear": null,
"color": "ffbb00",
"id": 6039365
}
]
// instead of 30 you can replace with your value
let filteredArray = res.filter(o => o.suggested_price > 30)
console.log("filtered Array greater than 30", filteredArray)
// addition if you want to reduce the array , you can do the below
let totalOfSuggPrice = filteredArray.reduce((a,c) => ({total: a.suggested_price + c.suggested_price}))
console.log("sum of the filtered array - total of the suggested price",totalOfSuggPrice )
I have 2 arrays of objects: itemsList and itemsFetched. All of the objects inside each array have the same structure (nr of key/values). One of those keys has the same 'meaning' but a different name (item_id on itemsList, id on itemsFetched ). Their values are the same.
I need to filter the itemsList array and leave only the objects that have the item_id value equal to the id value on itemsFetched. Then copy(add) the key/value count from each object on the itemsFetched array (which matches the item_id=id) to the filtered array.
I've a working code but I'm sure it isnt the best way to solve this problem. I've already asked something similar before (regarding the 'filter' part) which solved my problem, but since I had to add the 'count' part after the filtering, I ended up refactoring the whole thing.
itemsList (sample)
[
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
},
{
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
},
{
"id": 401,
"name": "Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 901,
"name": "Incubator (Unlimited)",
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}
]
itemsFetched (sample)
[
{
"item_id": 1,
"count": 50,
"unseen": true
},
{
"item_id": 401,
"count": 2,
"unseen": true
},
{
"item_id": 901,
"count": 1,
"unseen": true
}
]
resultArray (what I want in the end)
[
{
"id": 1,
"name": "Pokeball",
"count": 50,
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png",
},
{
"id": 401,
"name": "Incense",
"count": 2,
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 901,
"name": "Incubator (Unlimited)",
"count": 1,
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}
]
my current code (working)
let arr = [];
itemsFetched.forEach((item) => {
itemsList.forEach((item2) => {
if (item.item_id === item2.id) {
arr.push({
"id": item.item_id,
"name": item2.name,
"count": item.count,
"img": item2.img
});
}
});
});
PS: I'm able to use ES6/7 syntax/features.
You can use hash map to reduce Time complexitly, your algorithm is O(m*n), The follow is O(m+n+r)
const itemsMap = itemsList.reduce((map, item) => {
map[item.id] = item
return map
}, {})
const results = itemsFetched
.filter((item) => itemsMap.hasOwnProperty(item.item_id))
.map((item) => ({
id: item.item_id,
name: itemsMap[item.item_id].name,
count: item.count,
img: itemsMap[item.item_id].img,
}))
Use a for ... of loop (an ES6 feature) in conjunction with Array#map.
This makes it much easier to return the merged object the first time you find a match, which is a logically optimization because neither list should contain more than one entry with a given id.
const result = itemsFetched.map(data => {
for (let item of itemsList) {
if (data.item_id === item.id) {
return {
id: item.id,
name: item.name,
count: data.count,
img: item.img
}
}
}
})
Snippet:
const itemsList = [{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
}, {
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
}, {
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
}, {
"id": 401,
"name": "Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
}, {
"id": 901,
"name": "Incubator (Unlimited)",
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}]
const itemsFetched = [{
"item_id": 1,
"count": 50,
"unseen": true
}, {
"item_id": 401,
"count": 2,
"unseen": true
}, {
"item_id": 901,
"count": 1,
"unseen": true
}]
const result = itemsFetched.map(data => {
for (let item of itemsList) {
if (data.item_id === item.id) {
return {
id: item.id,
name: item.name,
count: data.count,
img: item.img
}
}
}
})
console.log(result)
One way to improve is to use for..of statement instead of forEach for the inner loop. This helps break from the loop once the id matches. There is no direct way to break from forEach method.
let arr = [];
itemsFetched.forEach((item) => {
for (let item2 of itemsList) {
if (itemsFetched.item_id === itemsList.id) {
arr.push({
"id": itemsFetched.item_id,
"name": itemsList.name,
"count": itemsFetched.count,
"img": itemsList.img
});
break;
}
}
});
Like this?
var itemsList = [
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
},
{
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
},
{
"id": 401,
"name": "Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 901,
"name": "Incubator (Unlimited)",
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}
];
var itemsFetched = [
{
"item_id": 1,
"count": 50,
"unseen": true
},
{
"item_id": 401,
"count": 2,
"unseen": true
},
{
"item_id": 901,
"count": 1,
"unseen": true
}
]
let arr = [];
itemsFetched.forEach((item) => {
itemsList.forEach((item2) => {
if (item.item_id == item2.id) {
arr.push({
"id": item.item_id,
"name": item2.name,
"count": item.count,
"img": item2.img
});
}
});
});
console.log(arr);
I have a JSON dataset which could be very large when it returns, with the following structure for each object:
{
"ctr": 57,
"averageECPC": 23,
"cost": 2732.54,
"margin": 66,
"profit": 2495.9,
"property": {
"value": "Izzby",
"uri": "/Terrago/2"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 2573.13,
"compare": 0
},
"children": [{
"ctr": 79,
"averageECPC": 54,
"cost": 3554.78,
"margin": 88,
"profit": 3145.81,
"property": {
"value": "Comvex",
"uri": "/Octocore/4"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 1247.92,
"compare": 0
}
}]
}
Now I want to search all objects in the array and return only objects which include a string of some sort, but I only want to search certain properties.
I basically have another array which contains the keys I want to search, e.g.
const iteratees = ['ctr', 'property.value', 'status.stage']
I have lodash available within the project, but I have no idea where to start.
Any ideas?
You could use filter(), some() and reduce() to do this.
const iteratees = ['ctr', 'property.value', 'status.stage'];
var searchFor = 'lo';
var result = arr.filter(function(o) {
return iteratees.some(function(e) {
var res = e.split('.').reduce(function(a, b) {
if(a) return a[b];
}, o);
if(res) {
if((res).toString().indexOf(searchFor) != -1) return true;
}
})
})
var arr = [{
"ctr": 'lorem',
"averageECPC": 23,
"cost": 2732.54,
"margin": 66,
"profit": 2495.9,
"property": {
"value": "Izzby",
"uri": "/Terrago/2"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 2573.13,
"compare": 0
},
"children": [{
"ctr": 79,
"averageECPC": 54,
"cost": 3554.78,
"margin": 88,
"profit": 3145.81,
"property": {
"value": "Comvex",
"uri": "/Octocore/4"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 1247.92,
"compare": 0
}
}]
}, {
name: 'lorem',
ctr: 12,
property: {
value: 1
},
status: {
stage: 1
}
}, {
name: 'ipsum'
}]
const iteratees = ['ctr', 'property.value', 'status.stage'];
var searchFor = 'lo';
var result = arr.filter(function(o) {
return iteratees.some(function(e) {
var res = e.split('.').reduce(function(a, b) {
if (a) return a[b];
}, o);
if (res) {
if ((res).toString().indexOf(searchFor) != -1) return true;
}
})
})
console.log(result)