How to find sum of values of objects in array in dart? - arrays

I have an array that is like following:
[{name: Cibo, quantity: 3},
{name: Cibo, quantity: 2},
{name: Invia Regalo, quantity: 3},
{name: Invia Regalo, quantity: 1}]
How can I find the total quantity for these objects by combining the same names?
So output would look like:
[
{name: Invia Regalo, quantity: 4},
{name: Cibo, quantity: 5},
]
I have tried something like this, but does not work in Dart.
var categoryTotal = [];
category.forEach((category) {
print(category);
var categ =
categoryTotal.firstWhere((cat) => cat['name'] == category['name']);
print("Category is $categ");
if (categ != null) {
categ['quantity'] += category['quantity'];
} else {
categoryTotal.add(category);
}
});
print(categoryTotal);

I will in general not recommend the use of maps maps to handle objects that contains different types of values. Instead, use classes. It makes it a lot easier to write type safe code.
Also, I will not recommend using the .forEach() method when you have multiple lines of code since it can make it difficult to read. Instead, use a for-each loop.
I have made the following solution to handle your list of maps. The sumMap is for making the code more efficient by using a Map to handle the sums of quantity. The result are then created based on sumMap:
void main() {
final array = [
{'name': 'Cibo', 'quantity': 3},
{'name': 'Cibo', 'quantity': 2},
{'name': 'Invia Regalo', 'quantity': 3},
{'name': 'Invia Regalo', 'quantity': 1},
];
final sumMap = <String, int>{};
for (final map in array) {
sumMap.update(
map['name']! as String,
(sum) => sum + (map['quantity']! as int),
ifAbsent: () => map['quantity']! as int,
);
}
final result = [
for (final entry in sumMap.entries)
{'name': entry.key, 'quantity': entry.value}
];
print(result);
// [{name: Cibo, quantity: 5}, {name: Invia Regalo, quantity: 4}]
}

You need to add orElse: () => null to avoid exeption. So, final code would look like this:
var categoryTotal = [];
category.forEach((category) {
var categ = categoryTotal.firstWhere(
(cat) => cat['name'] == category['name'],
orElse: () => null,
);
if (categ != null) {
categ['quantity'] += category['quantity'];
} else {
categoryTotal.add(category);
}
});
print(categoryTotal);

Related

typescript how to find inside an array that is already in an array?

I want to find a value inside an array that is already inside an array.
To give an example of my array:
[
{
ConcessionId: 1,
ConcessionName: "Coyotes",
KnownAs: [
{
TeamId: 1,
Name: "Arizona Coyotes",
},
{
TeamId: 2,
Name: "Phoenix Coyotes",
}
]
},
{
ConcessionId: 2,
ConcessionName: "Devils",
KnownAs: [
{
TeamId: 3,
Name: "Colorado Rockies",
},
{
TeamId: 4,
Name: "New-Jersey Devils",
}
]
}
]
What I want is when Icall my function it returns me the team name.
For example, I the parameter value is 3, I want Colorado Rockies as a name:
public getInfo(_TeamID) {
const concession: ConcessionInfo[] = this.concessionList$.filter(function (x) {
x.KnownAs.filter( (y)=> {
y.TeamId= +_TeamID;
return y.Name;
})
})
}
I try so many different way with filter. But never get something good. Never works.
I can make a double .foreach , for each array. but I think a better method exist than making a double loop.
Thanks
Instead of using the filter method (which is in fact working similar as a for loop), you could do forEach on both arrays. For your current data structure, there is no other way around it.
getInfo = (_TeamID) => {
let teamName = '';
this.concessionList$.forEach(entry => {
entry.KnownAs.forEach(team => {
if(team.TeamId === _TeamID){
teamName = team.Name;
return; // break the loop.
}
})
});
return teamName;
}
Here is a working example
https://stackblitz.com/edit/double-for-lopp
EDIT
If you have a look at the polyfill implementation of filter from Mozilla https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter which is in equivalent to the native implementation of filter, you can see that it is looping through the whole array, the same way as a forEach loop. The difference is that the filter method will return a new array based on the boolean condition inside the callback function, while a forEach loop does not return anything.
Assuming myArray is contains the data you provided.
The following code will work if you're using Typescript 3.7 and above.
public getInfo(teamId: number): string | undefined {
const team = this.concessionList$
.map(concession => concession.KnownAs)
.reduce((a, b) => a.concat(b), [])
.find(team => team.TeamId === teamId)
return team ? team.Name : undefined
}
Usage:
this.getInfo(3) // Colorado Rockies
Ok how this work?
You have to understand what is find. For example:
const result = [{name: 'foo', age: 1}, {name: 'bar', age: 2}]
.find(people => people.name === 'foo')
console.log(result) // {name: 'foo', age: 1}

How to find objects with the same property values in an Array of Objects in typescript?

I have an array of objects
var myArray = [
{id: 1, name: 'Foo Bar', email: 'foo#bar.com'},
{id: 2, name: 'Bar Foo', email: 'bar#foo.com'},
{id: 3, name: 'Joe Ocean', email: 'joe#ocean.com'},
{id: 3, name: 'Jenny Block', email: 'foo#bar.com'},
];
I am expecting the following output:
commonIdsObjects = [
{id: 3, name: 'Joe Ocean', email: 'joe#ocean.com'},
{id: 3, name: 'Jenny Block', email: 'foo#bar.com'},
]
I assume that you want the output to be a single array containing all the duplicate entries, even if some of those entries have different ids. For example, if you had added {id: 2, name: 'Fishy Joe', email: 'com#foo.bar'} to myArray, the resulting commonIdsObjects would be an array of four items: two for id: 2 and two for id: 3. If this is not what you want then you should take care to specify exactly the expected behavior.
Anyway, assuming you have a type corresponding to the elements of myArray, like this:
type Elem = typeof myArray[number];
And assuming your target runtime has access to the Object.values() and Array.prototype.flat() methods, then you can write
const commonIdsObjects = Object.values(
myArray.reduce<{ [k: number]: Elem[] }>(
(a, v) => ((a[v.id] || (a[v.id] = [])).push(v), a), {}
)
).filter(c => c.length > 1).flat(1);
What we're doing is using myArray.reduce() to build an object whose keys correspond to your elements' id values, and whose values are arrays of elements with those id. We convert this object into an array of arrays of elements, keep only those whose lengths are more than one (i.e., any id with more than one element corresponding to it), and flatten into a single array.
This will produce the desired result:
console.log(JSON.stringify(commonIdsObjects));
// [{"id":3,"name":"Joe Ocean","email":"joe#ocean.com"},
// {"id":3,"name":"Jenny Block","email":"foo#bar.com"}]
If you don't have access to Object.values() and [].flat() you can use Object.keys() and [].reduce() instead:
type ElemsById = { [k: string]: Elem[] }
const commonIdsObjects2 = ((o: ElemsById) => Object.keys(o).map(k => o[k]))(
myArray.reduce<ElemsById>(
(a, v) => ((a[v.id] || (a[v.id] = [])).push(v), a), {}))
.filter(c => c.length > 1).reduce<Elem[]>((a, v) => (a.push(...v), a), []);
console.log(JSON.stringify(commonIdsObjects2)); // same
which is essentially the same algorithm. Or you could do this algorithm the purely-imperative-programming way with various for loops:
const elemsById: ElemsById = {};
for (let v of myArray) {
if (!elemsById[v.id]) {
elemsById[v.id] = []
}
elemsById[v.id].push(v);
}
const commonIdsObjects3: Elem[] = []
for (let k in elemsById) {
if (elemsById[k].length <= 1) {
continue;
}
for (let v of elemsById[k]) {
commonIdsObjects3.push(v);
}
}
console.log(JSON.stringify(commonIdsObjects3)); // same
Okay, hope that helps; good luck!
Playground link to code
var myArray = [
{ id: 1, name: "Foo Bar", email: "foo#bar.com" },
{ id: 2, name: "Bar Foo", email: "bar#foo.com" },
{ id: 3, name: "Joe Ocean", email: "joe#ocean.com" },
{ id: 3, name: "Jenny Block", email: "foo#bar.com" }];
const commonIdsObjects = myArray.filter(x => x.id === 3);
console.log(commonIdsObjects);

Get only values from the array of array using angular js

I got an array from database as
[
{id:
{unitno: 'abc'},
amount: 100},
{id:
{unitno: 'xyz'},
amount: 150}
]
Now my required answer is that should be in the following format,
[["abc",100],
["xyz",150]]
But after some coding I got an array of Array as shown below in the console
[0:[0:"abc",1:100]
1:[0:"xyz",1:150]]
Before question down / marking duplicate please read my requirement, and if its there then mark it and please post that link as per my required solution so i can get my solution from there
So any help will be great help....
You can do like this:
data = [
{id:
{unitno: 'abc'},
amount: 100},
{id:
{unitno: 'xyz'},
amount: 150}
]
var array =[]
data.forEach(function(item){
var tmpArray = []
tmpArray.push(item.id.unitno,item.amount)
array.push(tmpArray)
})
Now you will get your required data in the array.
I don't know how you got this below code, but that's invalid Array
[0:[0:"abc",1:100] 1:[0:"xyz",1:150]]
For your desired output you can do it with JavaScript, no need angular. Just run a simple for loop.
var temp1 = [{
id: {
unitno: 'abc'
},
amount: 100
}, {
id: {
unitno: 'xyz'
},
amount: 150
}];
var eee = [];
temp1.forEach(function(el) {
eee.push([el.id.unitno, el.amount])
});
console.log('eee:', eee);
Hope this is what you needed.
var arr = [{
id : { unitno: 'abc' },
amount: 100
},{
id : { unitno: 'xyz' },
amount: 150
}];
var result = [];
for (var i = 0; i < arr.length; i++) {
var newArray = [];
newArray.push( arr[i]["id"]["unitno"] );
newArray.push( arr[i]["amount"] );
result.push( newArray );
}
console.log( result );

I want to concatenate these two objects to get the following result $scope.all=[ lead value and contact value]

$scope.lead = [
{name: 'raj', email:'raj#gmail.com'}
];
$scope.contact=[
{name: 'James', email:'james#gmail.com'}
];
Looks like more related to JS than angular itself.
$scope.lead = [{name: 'raj', email:'raj#gmail.com'}];
$scope.contact =[{name: 'James', email:'james#gmail.com'}];
$scope.all = {};
$scope.all.lead = $scope.lead;
$scope.all.contact = $scope.contact;
console.log(JSON.stringify($scope.all))

Shorten an array or collection with an array of fields

Scenario:
you have an array,
you have an array of some ids (eg: [1,3]),
you want to get a shortened array.
I cannot find how to do so if not in the lengthy way:
_.filter(... function (id) { return id==1 || id==3 })
Question: does such someMethod1 exist in underscore.js?
var frdsArr =
[
{id: 1, name: 'moe', age: 40},
{id: 2, name: 'larry', age: 50},
{id: 3, name: 'curly', age: 60}
];
var goodFrdsArr = _.someMethod1( frdsArr, 'id', [1, 3] );
/*
goodFrdsArr is [
{id: 1, name: 'moe', age: 40},
{id: 3, name: 'curly', age: 60}
];
*/
The same question with backbone.js: what about someMethod2?
var Friend = Backbone.Model.extend({});
var FriendsCollection = Backbone.Collection.extend({
model: Friend
});
var friendsCollection = new FriendsCollection( frdsArr );
var goodFriendsCollection = friendsCollection.someMethod2( 'id', [1,3] );
/*
goodFriendsCollection contains 2 instances of Friend Models
*/
Once you have found a suitable function, you can extend Underscore with _.mixin to simplify later calls. For example, you could create _.restrict to match your _.someMethod1 signature:
_.mixin({
// filter a list on an attribute having to match a list of values
// _.indexOf accepts an optional isSorted argument so let's pass it
restrict: function(list, attr, values, isSorted) {
return _.filter(list, function(obj) {
return _.indexOf(values, obj[attr], isSorted) !== -1;
});
}
});
var goodFrdsArr = _.restrict(frdsArr, 'id', [1, 3]);
See http://jsfiddle.net/nikoshr/cf0qs5gh/ for a demo
With this setup, you can modify Backbone.Collection's prototype to give all your collections this new capacity (more or less taken from the Backbone source code):
Backbone.Collection.prototype.restrict = function() {
var args = [].slice.call(arguments);
args.unshift(this.models);
return _.restrict.apply(_, args);
};
var friendsCollection = new Backbone.Collection(frdsArr);
var goodfriends = c.restrict('id', [1, 3]); //an array with 2 models
http://jsfiddle.net/nikoshr/cf0qs5gh/1/
var frdsArr =
[
{id: 1, name: 'moe', age: 40},
{id: 2, name: 'larry', age: 50},
{id: 3, name: 'curly', age: 60}
];
var filteredIDs = [1,3];
var filteredFrnds = _.filter(frdsArr, function(frnd){
return _.contains(filteredIDs, frnd.id);
})
console.log(filteredFrnds);
Make use of filter and contains
FIDDLE

Resources