can I get the sum of amount if I have an array like the one below?
[{"_id":"5e154cf38c52231ee19f8",
"refunds":[
{"_id":"5e38f10a754fcf3d48015",
"reason":"refund 1",
"amount":50000,
]},
{"_id":"5e1578b48c52231ee19f8",
"refunds":[
{"_id":"5e37e09ef9ea5e3784043",
"reason":"refund 1",
"amount":100000,
{"_id":"5e37e12a02c27c14580a1",
"reason":"refund 2",
"amount":100000,
{"_id":"5e38f02b754fcf3d48015",
"reason":"refund 3",
"amount":50000,
]},
{"_id":"5e1578b48c52231ee19f8",
"refunds":[]
}]
I hope to get res = 300000
This should be relatively straightforward, we create a flat array of all refund objects using flatMap, then we'll use reduce to sum the total amount.
I've added another function, sumRefundAmountsII to workaround JavaScript environments that do not support.flatMap (pre ES2019)
const data = [ { "_id": "5e154cf38c52231ee19f8", "refunds": [ { "_id": "5e38f10a754fcf3d48015", "reason": "refund 1", "amount": 50000 } ] }, { "_id": "5e1578b48c52231ee19f8", "refunds": [ { "_id": "5e37e09ef9ea5e3784043", "reason": "refund 1", "amount": 100000 }, { "_id": "5e37e12a02c27c14580a1", "reason": "refund 2", "amount": 100000 }, { "_id": "5e38f02b754fcf3d48015", "reason": "refund 3", "amount": 50000 } ] }, { "_id": "5e1578b48c52231ee19f8", "refunds": [] }];
function sumRefundAmounts(array) {
// Get an array of all refunds.
const refunds = array.flatMap(obj => obj.refunds);
// Sum amount for each refund.
return refunds.reduce((sum, refund) => {
return sum + refund.amount;
}, 0);
}
console.log("Total amount:", sumRefundAmounts(data));
// Use this function if your JavaScript environment complains about .flatMap
function sumRefundAmountsII(array) {
// Use a work around if we don't have flatMap...
const refunds = [].concat.apply([], array.map(obj => obj.refunds));
// Sum amount for each refund.
return refunds.reduce((sum, refund) => {
return sum + refund.amount;
}, 0);
}
console.log("Total amount (no flat map):", sumRefundAmountsII(data));
Before answering ... I assume 2 things -
1st - you are looking answer in the Java. 2nd - And you can do things much easier way in java List :
Let we make 2 classes Refund & Composite (Containing List)-
Refund Class -
package com.sabre.ticketing.dhs.service.create.domain;
public class Refund {
String _id;
String reason;
int amount;
public Refund(String _id, String reason, int amount) {
this._id = _id;
this.reason = reason;
this.amount = amount;
}
public int getAmount() {
return amount;
}
}
And here is Composite Class as -
package com.sabre.ticketing.dhs.service.create.domain;
import java.util.List;
public class Composite {
String _id;
List<Refund> refunds;
public Composite(String _id, List<Refund> refunds) {
this._id = _id;
this.refunds = refunds;
}
public List<Refund> getRefunds() {
return refunds;
}
}
The calculation technique is in SumCalc class -
package com.sabre.ticketing.dhs.service.create.domain;
import java.util.ArrayList;
import java.util.List;
public class SumCalc {
public static void main(String[] args){
List<Composite> composites = List.of(new Composite("5e154cf38c52231ee19f8", List.of(new Refund("5e38f10a754fcf3d48015", "refund 1", 50000))),
new Composite("5e154cf38c52231ee19f8",
List.of(new Refund("5e37e09ef9ea5e3784043", "refund 1", 100000),
new Refund("5e37e12a02c27c14580a1", "refund 2", 100000),
new Refund("5e38f02b754fcf3d48015", "refund 3", 50000))),
new Composite("5e154cf38c52231ee19f8", new ArrayList<>()));
// Basically get you Json converted into composites list.. for simplicity and dont want to jackson thing i have initialized list as new ..
Integer finalSum = composites.stream()
.map(Composite::getRefunds)
.flatMap(List::stream)
.map(Refund::getAmount)
.reduce((sum, val) -> sum + val)
.orElse(0);
System.out.println("final Sum is " + finalSum);
}
}
Run the SumClac ...
final Sum is 300000
Process finished with exit code 0
Related
I have the following response from API
"features": [
{
"name": "Safety",
"_id": "636a638959d10a2603b8d645",
"values": [
Array of String
]
},
{
"name": "Entertainment",
"_id": "636a64312bbe0cd292a1ffc6",
"values": [
Array of String
]
Which I decode it with :
struct Feature : Codable , Hashable{
var name : String = ""
var values : [Value] = []
}
struct Value : Codable, Hashable{
var value : String = ""
var unit : String = ""
}
And in the view is render it like :
var body: some View {
VStack{
HStack{
Text("Choose Your Features").font(Font.body.bold())
Spacer()
}.padding(.leading, 15)
ScrollView(.vertical, showsIndicators: false){
VStack{
ForEach(Array(features.enumerated()), id: \.offset) { featureIndex, feature in
HStack{
Text(feature.name).font(Font.body.bold())
Spacer()
}.padding(.bottom , 10)
ScrollView(.horizontal, showsIndicators: false){
HStack(spacing : 10){
ForEach(Array(feature.values.enumerated()), id: \.offset) { valueIndex, value in
FeatureCell(isSelected: $isSelected, value: value).onTapGesture{
// here
}
}
}
Divider().padding(10)
}
}.padding(15)
}
}
}
}
The user may select multiple item from each feature values list, Now Im really confused about how to store these selections in an array of features object again, I tried almost every thing like Array, Set and Dictionaries but could not reach any solution.
Update : This is the json object I should send back
{
"features": [
{
"Safety": [
"value1",
"value9",
"value3"
]
},
{
"Entertainment": [
"value7",
"value2",
"value8"
]
}
]
}
Any help or ideas will be much appreciated
You usually want to use a Set to store which items are selected. This set should be a State variable instantiated in the parent view. The onTapGesture closure will add or remove the value to the set. If the FeatureCell needs to know whether the value is selected, simply use the .contains method.
struct FeatureValueSelectionView: View {
// The feature whose values we are displaying
let feature: Feature
// Note: You may have to manually conform Value to the Hashable protocol
#State private var selectedValues = Set<Value>()
var body: some View {
ForEach(feature.values) { value in
FeatureCell(selected: selectedValues.contains(value), value: value)
.onTapGesture { selectedValues.toggle(value) }
}
}
}
For toggling a value in a set, I like to use this simple extension:
extension Set {
public mutating func toggle(_ element: Element) {
if self.contains(element) {
self.subtract([element])
} else {
self.insert(element)
}
}
}
In tableview, each cell with key and value labels, i can able to pass static key value to tableview but now trying to get data from Json response to show in tableview.
here is my json response:
{
"d": {
"results": [
{
"__metadata": {
"id": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"uri": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"type": "Z_MM_PO_01_SRV.POItemSet"
},
"PoDocNo": "4500022401",
"Item": "00010",
"Material": "RMECC_MOB1",
"StorageLocation": "3001",
"MatGroup": "00107",
"Quantity": "2.000",
"OrderUnit": "KG",
"NetPrice": "1000.000",
"UnitofPrice": "1.000",
"ItemCat": "0",
"Requistor": ""
},
{
"__metadata": {
"id": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"uri": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"type": "Z_MM_PO_01_SRV.POItemSet"
},
"PoDocNo": "4500022401",
"Item": "00020",
"Material": "RMECC_MOB1",
"StorageLocation": "3001",
"MatGroup": "00107",
"Quantity": "2.000",
"OrderUnit": "KG",
"NetPrice": "1000.000",
"UnitofPrice": "1.000",
"ItemCat": "0",
"Requistor": ""
}
]
}
}
here i'm getting json response:
extension PoItemDetailsViewController {
func GetPoItemCount() {
if orderNo != nil {
// Call API
print("orderni::\(orderNo!)")
PoVendorListApiManager.sharedInstance.getPoListWithModel(orderString: orderNo!){ (json:JSON) in
// return json from API
if let categories = json["d"]["results"].dictionary {
print("catefory::\(self.categories)")
for (key, value) : (String, JSON) in categories {
self.dict[key] = value.object as AnyObject
}
print("dict:::\(self.dict)")
// for key in categories.keys {
// if let category =
categories[key]?.stringValue {
//
self.categories.updateValue(category, forKey: key)
// }
//
// }
}
print("catefory::\(self.categories)")
}
}
}
}//extension
here is my model:
import SwiftyJSON
struct poItems {
var key: String?
var value: String?
}
here is my static value i have passed to table view:
private var PoItems: [poItems]?
private var poVendorItemArray = [PoVendorModel]()
private func loadPoItems() -> [poItems] {
var tempItems = [poItems]()
let item1 = poItems.init(key: "Material#", value: "")
let item2 = poItems.init(key: "Quantity", value: "Bottles")
let item3 = poItems.init(key: "StorageLocation", value: "KP04")
let item4 = poItems.init(key: "PoDocNo", value: "KP Suppliers")
let item5 = poItems.init(key: "NetPrice", value: "1000")
return tempItems
}
how can i pass json reponse with key and value dynamically into tableview?
Any help much appreciates pls...
Please reread my answer in your earlier question (or read the JSON)
The value for results is an array
if let categories = json["d"]["results"].array {
print("category::\(self.categories)")
for category in categories {
for (key, value) in category {
print(key, value)
}
}
}
And – as suggested in many of your previous questions and in the comments – you are encouraged to drop SwiftyJSON and use Codable.
I'm about to use the database "Sembast" in Flutter.
Simple objects with data types like string and int are working properly. However, it becomes problematic when using Lists.
I have created an example and oriented myself on the following tutorial: https://resocoder.com/2019/04/06/flutter-nosql-database-sembast-tutorial-w-bloc/
In my example, there are fruits and leaves as objects. A fruit contains a list of leaves.
class Fruit {
final String id;
final String name;
final bool isSweet;
final List<Leaves> leaves;
...
}
class Leaves {
final String id;
final String name;
...
}
//Create a sample object
var leaveOne = Leaves(id: "1", name: "leaveOne");
var leaveTwo = Leaves(id: "2", name: "leaveTwo");
var leaveThree = Leaves(id: "3", name: "leaveThree");
var leavesList = List<Leaves>();
leavesList.add(leaveOne);
leavesList.add(leaveTwo);
leavesList.add(leaveThree);
var fruit = Fruit(id: "1", name: "Apple", isSweet: true, leaves: leavesList);
_fruitDao.insert(fruit);
// The fruitDao.insert makes following
Future insert(Fruit fruit) async {
await _fruitStore.add(await _db, fruit.toJson());
}
The JSON looks like that: {id: 1, name: Apple, isSweet: true, leaves: [Instance of 'Leaves', Instance of 'Leaves', Instance of 'Leaves']}
The ERROR is following:
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Invalid argument(s): value Instance of 'Leaves' unsupported type Leaves
As pointed at, Instance of 'Leaves' is not a valid type so each Leave must be converted as well. Hard to guess what you are doing without seeing your toJson() but something like this should work (could be largely optimized):
class Fruit {
final String id;
final String name;
final bool isSweet;
final List<Leaves> leaves;
Fruit({this.id, this.name, this.isSweet, this.leaves});
Map<String, dynamic> toJson() => <String, dynamic>{
'id': id,
'name': name,
'isSweet': isSweet,
'leaves': leaves?.map((leave) => leave.toJson())?.toList(growable: false)
};
}
class Leaves {
final String id;
final String name;
Leaves({this.id, this.name});
Map<String, dynamic> toJson() => <String, dynamic>{'id': id, 'name': name};
}
and your json should look like something this this:
{
"id": "1",
"name": "Apple",
"isSweet": true,
"leaves": [
{
"id": "1",
"name": "leaveOne"
},
{
"id": "2",
"name": "leaveTwo"
},
{
"id": "3",
"name": "leaveThree"
}
]
}
Here is an example in addition to #alextk answer with converting to and from without any code generation or library's.
class Fruit {
final String id;
final String name;
final bool isSweet;
final List<Leaves> leaves;
Fruit({this.id, this.name, this.isSweet, this.leaves});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'isSweet': isSweet,
'leaves': leaves.map((leave) => leave.toMap()).toList(growable: false)
};
}
static Fruit fromMap(Map<String, dynamic> map) {
return Fruit(
id: map['id'],
name: map['name'],
isSweet: map['isSweet'],
leaves: map['leaves'].map((mapping) => Leaves.fromMap(mapping)).toList().cast<Leaves>(),
);
}
}
class Leaves {
final String id;
final String name;
Leaves({this.id, this.name});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
};
}
static Leaves fromMap(Map<String, dynamic> map) {
return Leaves(
id: map['id'],
name: map['name'],
);
}
}
For cases when you use freezed, I found this solution:
...
...
#freezed
class Fruit with _$Fruit {
//add this line
#JsonSerializable(explicitToJson: true)
const factory Fruit({...}) = _Fruit;
factory Fruit.fromJson(Map<String, dynamic> json) => _$FruitFromJson(json);
}
This is my second question in a few days about working with spring data rest and HATEOAS links.
tl;dr
How can my application use the link for 'manyToOne' attribute to populate the 'current value' for an html select drop down?
"Spring data rest" generated links behave differently than with "old school ids".
Context
Converting an app to spring JPA and spring data rest.
Simple 'product/category' table structure per below
I've added a projection name 'full' to 'join/get' descriptions
Tables
*Product*
---------
Product ID
Product Name
Category ID
*Category*
---------
Category ID
Category Name
Spring Data Rest Domain Objects
Product
#Entity
#Table(name="products")
public class Products
{
private static final long serialVersionUID = 5697367593400296932L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public long id;
public String product_name;
#ManyToOne(optional = false,cascade= CascadeType.MERGE)
#JoinColumn(name = "category_id")
private ProductCategory productCategory;
public Products(){}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Products(String product_name) {
this.product_name = product_name;
}
public String getProduct_name() {
return product_name;
}
public void setProduct_name(String product_name) {
this.product_name = product_name;
}
public ProductCategory getProductCategory()
{
return productCategory;
}
public void setProductCategory(ProductCategory pProductCategory)
{
productCategory = pProductCategory;
}
#Projection(name = "full", types = { Products.class })
interface VirtualProjection
{
String getProductName() ;
#Value("#{target.productCategory.category}")
String getCategory();
}
}
Product Category
#Entity
#Table(name="productcat")
public class ProductCategory implements Serializable{
private static final long serialVersionUID = 890485159724195243L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public long id;
public String category;
#OneToMany(mappedBy = "productCategory", cascade = CascadeType.ALL)
#JsonBackReference
Set<Products> products;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public Set<Products> getProducts() {
return products;
}
}
Problem: Impedance Mismatch between list of Categories, value in object
When the angular client retrieves a product, the product 'category link' for the product category looks like this:
href" : "http://localhost:8080/api/rest/products/8/productCategory"
When the client retrieves a list of 'product categories', the link for the category looks like this:
href": "http://localhost:8080/api/rest/productcat/4"
Here's the "select" code. The UI will only show select if "product.productCategory" maches one of the value for 'options'.
<select ng-model="product.productCategory >
<option value="http://localhost:8080/api/rest/productcat/1">Foo Product Type
</option>
<option value="http://localhost:8080/api/rest/productcat/2">Bar Product Type
</option>
<option value="http://localhost:8080/api/rest/productcat/3">Baz Product Type
</option>
</select>
Question
How do I code my server API to make "generated links" client
friendly? What's the Springiest approach?
Should I change the API to receive, for update, "values" rather than "IDs/Links", i.e. the Category Name,rather than the ID? (i.e. and look up the category by name and update it on the server side)
What javascript/angular tools and techniques do you recommend for working with links?
I coded around the problem by 'de-referencing' the "productCategory" value via javascript,
- retrieving the URL in the "productCategory" attribute, e.g.:
http://localhost:8080/api/rest/products/8/productCategory
replacing the "productCategory" attribute/url with the values from the HATEOAS links.
pItem[pPropName] = data._links.self.href;
This approach brings a lot of complexity for a simple drop down. It doesn't smell right.
De-reference code
function dereferenceProperty(pItem,pPropName )
{
var myRef = pItem._links[pPropName];
if (myRef && myRef.href)
{
var myUrl = myRef.href;
$http.get(myUrl).success(function (data, status)
{
pItem[pPropName] = data._links.self.href;
});
}
}
Usage
dereferenceProperty(pProduct,"productCategory");
After this 'de-refrence':
Angular/Browser populated the drop down correctly
an HTTP PATCH update the API (and tables) correctly
I don't completely understand what do you mean, but if you need to get Product list within ProductCategory or you need to get implicitly ProductCategory within Product you can use, for example, projections:
#Projection(name = "withProducts", types = ProductCategory.class)
public interface WithProducts {
String getName();
Set<Product> getProducts();
}
#Projection(name = "withCategory", types = Product.class)
public interface WithCategory {
String getName();
BigDecimal getPrice();
ProductCategory getCategory();
}
Then if you GET http://localhost:8080/api/productCategories/1?projection=withProducts you retrieve something like this:
{
"_embedded": {
"products": [
{
"name": "Product1",
"category": {
"name": "Category1"
},
"price": 1,
"_links": {
"self": {
"href": "http://localhost:8080/api/products/1"
},
"product": {
"href": "http://localhost:8080/api/products/1{?projection}",
"templated": true
},
"category": {
"href": "http://localhost:8080/api/products/1/category"
}
}
},
{
"name": "Product2",
"category": {
"name": "Category1"
},
"price": 2,
"_links": {
"self": {
"href": "http://localhost:8080/api/products/2"
},
"product": {
"href": "http://localhost:8080/api/products/2{?projection}",
"templated": true
},
"category": {
"href": "http://localhost:8080/api/products/2/category"
}
}
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/api/productCategories/1/products?projection=withCategory"
}
}
}
Or if you GET http://localhost:8080/api/products/1/category?projection=withProducts you retrieve something like this:
{
"name": "Category1",
"products": [
{
"name": "Product1",
"price": 1
},
{
"name": "Product2",
"price": 2
}
],
"_links": {
"self": {
"href": "http://localhost:8080/api/productCategories/1"
},
"productCategory": {
"href": "http://localhost:8080/api/productCategories/1{?projection}",
"templated": true
},
"products": {
"href": "http://localhost:8080/api/productCategories/1/products"
}
}
}
Working example.
I have a Solr Schema and I am trying to do Facet Pivoting on it by passing multiple fields in facet.pivot parameter while making a call through SolrJ. My Solr response looks something like below:
"facet_pivot": {
"boolean_value,int_value": [
{
"field": "boolean_value",
"value": false,
"count": 1,
"pivot": [
{
"field": "int_value",
"value": 364,
"count": 1
}
]
},
{
"field": "boolean_value",
"value": true,
"count": 2,
"pivot": [
{
"field": "int_value",
"value": 406,
"count": 1
},
{
"field": "int_value",
"value": 409,
"count": 1
}
]
}
]
}
How, can I parse the above response using SolrJ in form of Nested objects i.e. PivotField having relation of which int_value falls under which boolean_value.
SolrJ Version tried: 4.10.4
Update:
When you make a call through SolrJ check the SolrQuery that gets generated. In my above case the SolrQuery was:
facet.pivot=boolean_value&facet.pivot=int_value
Solr considers above pivots as two different ones and you won't get nested pivoting. For Nested Pivoting your SolrQuery should have
facet.pivot=boolean_value,int_value
I had the same problem and wrote a simple tester application. It queries Solr and writes the pivot values to StdOut as hierarchical Strings. If there are any suggestions to implement that more nicely, please let me know. Here's the code:
public class Tester {
public static final String HIERARCHICAL_FACET_SEPARATOR = "/";
public static void main(String[] args) throws SolrServerException, IOException {
CloudSolrClient solr = ... ;
SolrQuery query = new SolrQuery(...);
query.setFacet(true);
query.addFacetPivotField(new String[]{"field1,field2,field3"});
QueryResponse result = solr.query(query);
NamedList<List<PivotField>> facetPivot = result.getFacetPivot();
List<String> parsedPivotResult = parsePivotResult(facetPivot);
parsedPivotResult.forEach((s) -> {
System.out.println(s);
});
}
private static List<String> parsePivotResult(final NamedList<List<PivotField>> pivotEntryList) {
final Set<String> outputItems = new HashSet<>();
for (final Entry<String, List<PivotField>> pivotEntry : pivotEntryList) {
System.out.println("Key: " + pivotEntry.getKey());
pivotEntry.getValue().forEach((pivotField) -> {
renderOutput(new StringBuilder(), pivotField, outputItems);
});
}
final List<String> output = new ArrayList<>(outputItems);
Collections.sort(output);
return output;
}
private static void renderOutput(final StringBuilder sb, final PivotField field, final Set<String> outputItems) {
final String fieldValue = field.getValue() != null ? ((String) field.getValue()).trim() : null;
final StringBuilder outputBuilder = new StringBuilder(sb);
if (field.getPivot() != null) {
if (outputBuilder.length() > 0) {
outputBuilder.append(HIERARCHICAL_FACET_SEPARATOR);
}
outputBuilder.append(fieldValue);
outputItems.add(new StringBuilder(outputBuilder).append(" (").append(field.getCount()).append(")").toString());
field.getPivot().forEach((subField) -> {
renderOutput(outputBuilder, subField, outputItems);
});
} else {
if (outputBuilder.length() > 0) {
outputBuilder.append(HIERARCHICAL_FACET_SEPARATOR);
}
outputBuilder.append(fieldValue);
outputItems.add(outputBuilder.append(" (").append(field.getCount()).append(")").toString());
}
}
}