Traversing through an array of objects - loops

{
"Catalog": {
"shirts": [
{
"id": "93453951-8427394-234723908",
"name": "Demin Shirt",
"price": 100.0,
"category": "Random Category",
"available": true,
},
{
"id": "93453951-8427394-40325978",
"name": "Random Shirt",
"price": 500.0,
"category": "Random Category",
"available": true,
}
],
"Jeans": [
{
"id": "4802345-348579-5983452-23423",
"name": "Bare Denim Jeans",
"price": 2000.0,
"category": "Some Category",
"available": true,
},
{
"id": "143682137-3481293-239842",
"name": "Levis jeans",
"price": 1000.0,
"category": "Some Category",
"available": true,
}
]
}
}
How do I traverse this array of objects such that I am able to display all the different types of shirt under the category shirt and all the jeans under the heading jeans.
Something like this:
Shirts
Denim Shirt.
Random Shirt
Jeans
Bare Denim Jeans
Levis jeans

Generic Solution
This is an object, not a list, so you can't just plug it into a loop. If you want to loop through all the values and sub-values, you will have to do it recursively.
void recurseObject(dynamic value) {
if (value is List) {
// value is a list, iterate over its children
for (var child in value) {
recurseObject(object);
}
} else if (value is Map) {
// value is an object, iterate over its keys and recurse the corresponding values
for (var key in object.keys) {
print(key);
recurseObject(object[key]);
}
} else {
// value is a primitive, so just print it
print(value);
}
}
Specific to your Object
If your object has a set structure, then you can just grab all the bits you want and set up some nested loops.
final catalog = rootObj['Catalog'] as Map<String, Dynamic>;
for (var category in catalog.keys) {
final categoryList = catalog[category] as List<dynamic>;
print(category);
for (var value in categoryList) {
final name = value['name'];
print(name);
}
}

What you have there is pure JSON. You need to first convert it into a Dart object.
There are a few ways to do the conversion. I've found the easiest way is to use an online converter such as this website: https://app.quicktype.io/
After you convert your JSON to an object, you could traverse it like this:
printCatalog() {
var catalog =
Catalog.fromRawJson("Here's where you need to pass in your JSON");
print("Shirts: ");
catalog.shirts.forEach((shirt) {
print(shirt.name);
});
print("Jeans: ");
catalog.jeans.forEach((jean) {
print(jean.name);
});
}

Just use dart:convert library, and json.decode. Then access whatever you want in your json.
I fixed your JSON as it wasn't set up right, here is the complete solution.
import 'dart:convert';
void main() {
var jsonstring = '''{
"Catalog": {
"shirts": [{
"id": "93453951-8427394-234723908",
"name": "Demin Shirt",
"price": 100.0,
"category": "Random Category",
"available": "true"
},
{
"id": "93453951-8427394-40325978",
"name": "Random Shirt",
"price": 500.0,
"category": "Random Category",
"available": true
}
],
"Jeans": [{
"id": "4802345-348579-5983452-23423",
"name": "Bare Denim Jeans",
"price": 2000.0,
"category": "Some Category",
"available": true
},
{
"id": "143682137-3481293-239842",
"name": "Levis jeans",
"price": 1000.0,
"category": "Some Category",
"available": true
}
]
}
}''';
Map<String, dynamic> data = json.decode(jsonstring);
print("--COOL SHIRTS--");
for (var shirt in data["Catalog"]["shirts"]) {
print(shirt["name"]);
}
print("\n--COOL JEANS--");
for (var jeans in data["Catalog"]["Jeans"]) {
print(jeans["name"]);
}
}
Output:
--COOL SHIRTS--
Demin Shirt
Random Shirt
--COOL JEANS--
Bare Denim Jeans
Levis jeans

Related

How to update array inside MongoDB document

Can someone help me with a solution to update an array object inside the MongoDB document, I've tried a couple of methods but still it's to updating, here is my document that I want to update the array in the document.
{
"title": "Products",
"description": "test",
"image": "bdd8510d75f6e83ad308d5f306afccef_image.jpg",
"_created_at": "2021-06-07T20:51:08.316Z",
"ratingCount": 0,
"ratingTotal": 0,
"placeListSave": [
{
"objectId": "g70brr45pfi",
"name": "Kale",
"email": "null",
"strBrandLogo": "84de8865e3223d1ca61386355895aa04_image.jpg",
"storeNumber": "56",
"phone": "0815342119",
"createdAt": "2021-06-10T10:19:53.384Z",
"image": "ad1fb7602c2188223fd891a52373cb9d_image.jpg"
},
{
"objectId": "0qokn33p773",
"name": "Apple",
"email": null,
"strBrandLogo": null,
"storeNumber": "01",
"phone": "011 393 8600",
"createdAt": "2021-06-11T03:11:17.342Z",
"image": "8cfcbf2bcb5e3b4ea8ade44d3825bb52_image.jpg"
}
]
}
So I only want to update the apple object and change the data, I've tried the following code but doesn't seem to work.
`
var db = client.db("test");
try {
db.collection("ShoppingCentres").updateOne({
"title": req.body.product,
"placeListSave.objectId": req.body.id,
}, {
$set: {
"placeListSave.$.email": req.body.email,
"placeListSave.$.storeNumber": req.body.storeNumber,
"placeListSave.$.phone": req.body.phone,
"placeListSave.name": req.body.name,
},
});
res.json("client");
} catch (e) {
console.log("verify", e);
}
});`
arrayFilters seems suitable here:
db.collection.update({
"title": "Products",
"placeListSave.objectId": "0qokn33p773",
},
{
$set: {
"placeListSave.$[x].email": "test#some.email",
"placeListSave.$[x].storeNumber": "test",
"placeListSave.$[x].phone": "test",
"placeListSave.$[x].name": "test"
}
},
{
arrayFilters: [
{
"x.objectId": "0qokn33p773"
}
]
})
explained:
Add array filter called "x" with the objectId for the element that you need to update and use this filter in the $set stage to update the necessary elements.
Hint: To speed up the update you will need to add index on title field or compound index on title+placeListSave.objectId
playground

Angular *ngFor: Display only unique property "category" value and lowest price in each "category"

I have an array with objects having "category" & "price" properties among others, in the Angular application I need to display only unique values of "category" property (Example: Economy, Premium & Deluxe) along with the lowest price in that category. I tried filtering it but was unable to achieve it. So can you please help how this can be achieved in Angular? Thank you.
In this example, I need to show:
Economy - Starts from 250USD
Premium - Starts from 400USD
Deluxe - Starts from 600USD
"hotelRooms": [
{
"price": {
"total": 250,
"currency": "USD"
},
"category": "Economy",
"subcategory": "single",
},
{
"price": {
"total": 350,
"currency": "USD"
},
"category": "Economy",
"subcategory": "double",
},
{
"price": {
"total": 450,
"currency": "USD"
},
"category": "Economy",
"subcategory": "family",
},
{
"price": {
"total": 400,
"currency": "USD"
},
"category": "Premium",
"subcategory": "single",
},
{
"price": {
"total": 500,
"currency": "USD"
},
"category": "Premium",
"subcategory": "double",
},
{
"price": {
"total": 600,
"currency": "USD"
},
"category": "Deluxe",
"subcategory": "single",
},
{
"price": {
"total": 700,
"currency": "USD"
},
"category": "Deluxe",
"subcategory": "double",
}
]
And in Angular:
<div *ngFor="let room of hotelRooms">
<span class="bold">{{ room.category }}</span> - Starts from {{ room.price.total}}{{ room.price.currency}}
</div>
From what I understand on this question, you need to group by category and next get the lowest price.amount for each category.
Concept (TL;DR)
Group By Category
1.1 Create an array for each category if the category array does not exist. Else reuse the created category array.
1.2 From each category array, find the lowest record based on price.amount.
1.3 If the result (from 1.2) return no value (undefined), first reset category array to empty array and add the current record to the category array. This ensures that each category will only have 1 record with the lowest price. Else just ignore it.
Data Transformation
2.1 Get the item from each category via iterate with key. It will return arrays.
2.2 Concat multiple arrays (from 2.1) into one array.
let groupByCategories = [];
groupByCategories = this.hotelRooms.reduce(function (previous, current) {
previous[current.category] = previous[current.category] || [];
let lowest = previous[current.category].find(
(x) =>
x.price.total < current.price.total
);
if (!lowest) {
previous[current.category] = [];
previous[current.category].push(current);
}
return previous;
}, Object.create(null));
this.hotelRooms = [].concat(
...Object.keys(groupByCategories).map((key) => {
return groupByCategories[key];
})
);
Sample Demo on StackBlitz

React Native - Manipulate array when object have same id

I have an array named ticketCart and it store ticket that users add, if I have an objects that looks something like this with same id on it, how can I distinguish with other objects that have a same id?
ADDEDKEY Array [
Object {
"desc": "tunjukkan tiket saat masuk",
"idTicket": "47",
"name": "vip",
"price": "70000",
"quota": "1459",
"status": "Available",
"type": "PAID",
"value": 2,
},
Object {
"desc": "tunjukkan tiket saat masuk",
"idTicket": "47",
"name": "vip",
"price": "70000",
"quota": "1459",
"status": "Available",
"type": "PAID",
"value": 2,
},
]
I tried to do something like forEach on it but it doesn't work, id (number) is still the same (In here, I'm using number as an id)
ticketCart.forEach((o, key) => {
ticketCart[key].number = key + 1;
})
Thanks
What do you mean by distinguish? What are you trying to achieve?
For example, you could identify each object by it's index in the array:
for (let i = 0; i < ticketCart.length; i++) {
ticketCart[i].number = ticketCart[i].id + "_" + i;
}

How to update object fields inside nested array and dynamically set a field value based on some inputs

I have been working on a Mongo database for a while. The database has some visits that have this form:
[
{
"isPaid": false,
"_id": "5c12bc3dcea46f9d3658ca98",
"clientId": "5c117f2d1d6b9f9182182ae4",
"came_by": "Twitter Ad",
"reason": "Some reason",
"doctor_services": "Some service",
"doctor": "Dr. Michael",
"service": "Special service",
"payments": [
{
"date": "2018-12-13T21:23:05.424Z",
"_id": "5c12cdb9b236c59e75fe8190",
"sum": 345,
"currency": "$",
"note": "First Payment"
},
{
"date": "2018-12-13T21:23:07.954Z",
"_id": "5c12cdbbb236c59e75fe8191",
"sum": 100,
"currency": "$",
"note": "Second payment"
},
{
"date": "2018-12-13T21:23:16.767Z",
"_id": "5c12cdc4b236c59e75fe8192",
"sum": 5,
"currency": "$",
"note": "Third Payment"
}
],
"price": 500,
"createdAt": "2018-12-13T20:08:29.425Z",
"updatedAt": "2018-12-13T21:42:21.559Z",
}
]
I need to find some query to update some field of a single payment based on the _id of the visit and _id of the payment that is inside of nested array. Also when you update a payment's sum to some number so that the sum of all payments is greater than or equal to price the field isPaid is automatically updated to true.
I have tried some queries in mongoose to achieve the first part but none of them seem to work:
let paymentId = req.params.paymentId;
let updatedFields = req.body;
Visit.update(
{ "payments._id": paymentId },
{
$set: {
"visits.$": updatedFields
}
}
).exec((err, visit) => {
if (err) {
return res.status(500).send("Couldn't update payment");
}
return res.status(200).send("Updated payment");
});
As for the second part of the question I haven't really come up with anything so I would appreciate at least giving some direction on how to approach it.

How can I change the attribute in dataset of Fusionchart?

Hi I am implementing a chart in my Angularjs Application, You can see this plunker http://jsfiddle.net/fusioncharts/73xgmacm/ The thing which I want to achieve is to change the value attribute to profit. How can I do this ? I want to display profit not values.
Regards
After 2 days I finally find out the answer. The thing is You cannot change the Fusionchart attribute value but you can change the attribute of your API once you fetched. I used a loop after I fetched the API and replace the 'profit' attribute with value in this way I made the chart. Yes The thing which i had been ignoring was the use of 'variable' instead of scope. If you see this example you would understand Example Here. I am sharing my code May be it helps someone else too.
Give below is my json array which i called tps.json
[
{
"index": "1",
"variantoption": "fan-green",
"company": "sk fans",
"quantity": "650",
"profit": "78296",
"loss": "8457",
"year": "2016"
},
{
"index": "2",
"variantoption": "fan-white",
"company": "al ahmed fans",
"quantity": "450",
"profit": "78296",
"loss": "8457",
"year": "2016"
},
{
"index": "3",
"variantoption": "fan-purple",
"company": "asia fans",
"quantity": "350",
"profit": "78296",
"loss": "8457",
"year": "2016"
},
{
"index": "4",
"variantoption": "fan-yellow",
"company": "falcon fans",
"quantity": "250",
"profit": "78296",
"loss": "8457",
"year": "2016"
}
]
and here is my controller
$http.get('js/tps.json').success(function (data) {
var chartdata = data;
var arrLength = chartdata.length;
console.log(arrLength);
for (var i = 0; i < arrLength; i++) {
if (chartdata[i]['profit'] && chartdata[i]['index']) {
chartdata[i].value = chartdata[i].profit;
delete chartdata[i].profit;
chartdata[i].label = chartdata[i].index;
delete chartdata[i].index;
console.log(chartdata);
}
}
console.log(chartdata);
FusionCharts.ready(function () {
var tps = new FusionCharts({
type: 'column2d',
renderAt: 'chart-container',
width: '500',
height: '300',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Monthly",
"xaxisname": "Month",
"yaxisname": "Revenue",
"numberprefix": "$",
"showvalues": "1",
"animation": "1"
},
"data" : chartdata
}
});
tps.render();
});
}
);
}
-Stay foolish stay hungry

Resources