What is the cleanest way to get the sum of numbers in a collection/list in Dart? - iteration

I don't like using an indexed array for no reason other than I think it looks ugly. Is there a clean way to sum with an anonymous function? Is it possible to do it without using any outside variables?

Dart iterables now have a reduce function (https://code.google.com/p/dart/issues/detail?id=1649), so you can do a sum pithily without defining your own fold function:
var sum = [1, 2, 3].reduce((a, b) => a + b);

int sum = [1, 2, 3].fold(0, (previous, current) => previous + current);
or with shorter variable names to make it take up less room:
int sum = [1, 2, 3].fold(0, (p, c) => p + c);

This is a very old question but
In 2022 there is actually a built-in package.
Just import
import 'package:collection/collection.dart';
and call the .sum extension method on the Iterable.
FULL EXAMPLE
import 'package:collection/collection.dart';
void main() {
final list = [1, 2, 3, 4];
final sum = list.sum;
print(sum); // prints 10
}
If the list is empty, .sum returns 0.
You might also be interested in list.average...

I still think this is cleaner and easier to understand for this particular problem.
num sum = 0;
[1, 2, 3].forEach((num e){sum += e;});
print(sum);
or
num sum = 0;
for (num e in [1,2,3]) {
sum += e;
}

There is not a clean way to do it using the core libraries as they are now, but if you roll your own foldLeft then there is
main() {
var sum = foldLeft([1,2,3], 0, (val, entry) => val + entry);
print(sum);
}
Dynamic foldLeft(Collection collection, Dynamic val, func) {
collection.forEach((entry) => val = func(val, entry));
return val;
}
I talked to the Dart team about adding foldLeft to the core collections and I hope it will be there soon.

Starting with Dart 2.6 you can use extensions to define a utility method on the List. This works for numbers (example 1) but also for generic objects (example 2).
extension ListUtils<T> on List<T> {
num sumBy(num f(T element)) {
num sum = 0;
for(var item in this) {
sum += f(item);
}
return sum;
}
}
Example 1 (sum all the numbers in the list):
var numbers = [1, 2, 3];
var sum = numbers.sumBy((number) => number);
Example 2 (sum all the Point.x fields):
var points = [Point(1, 2), Point(3, 4)];
var sum = points.sumBy((point) => point.x);

I'd just like to add some small detail to #tmaihoff's answer (about using the collection.dart package):
The sum getter he talks about only works for iterables of num values, like List<int> or Set<double>.
If you have a list of other object types that represent values (like Money, Decimal, Rational, or any others) you must map it to numbers. For example, to count the number of chars in a list of strings you can do:
// Returns 15.
['a', 'ab', 'abc', 'abcd', 'abcde'].map((e) => e.length).sum;
As of 2022, another way of doing it, is using the sumBy() method of the fast_immutable_collections package:
// Returns 15.
['a', 'ab', 'abc', 'abcd', 'abcde'].sumBy((e) => e.length), 15);
Note: I'm the package author.

I suggest you to create this function in any common utility file.
T sum<T extends num>(T lhs, T rhs) => lhs + rhs;
int, double, float extends num class so you can use that function to sum any numbers.
e.g.,
List<int> a = [1,2,3];
int result = a.reduce(sum);
print(result); // result will be 6

Herewith sharing my Approach:
void main() {
int value = sumTwo([1, 4, 3, 43]);
print(value);
}
int sumTwo(List < int > numbers) {
int sum = 0;
for (var i in numbers) {
sum = sum + i;
}
return sum;
}

If when using fold gives a double TypeError, you can use reduce:
var sum = [0.0, 4.5, 6.9].reduce((a, b) => a + b);

If you are planning on doing a number of mathematical operations on your list, it may be helpful to create another list type that includes .sum() and other operations by extending ListBase. Parts of this are inspired by this response with performance tweaks from this response.
import 'dart:collection';
import 'dart:core';
class Vector<num> extends ListBase<num> {
List<num> _list;
Vector() : _list = new List<num>();
Vector.fromList(List<num> lst): _list = lst;
void set length(int l) {
this._list.length=l;
}
int get length => _list.length;
num operator [](int index) => _list[index];
void operator []=(int index, num value) {
_list[index]=value;
}
// Though not strictly necessary, for performance reasons
// you should implement add and addAll.
void add(num value) => _list.add(value);
void addAll(Iterable<num> all) => _list.addAll(all);
num sum() => _list.fold(0.0, (a, b) => a + b) as num;
/// add additional vector functions here like min, max, mean, factorial, normalize etc
}
And use it like so:
Vector vec1 = Vector();
vec1.add(1);
print(vec1); // => [1]
vec1.addAll([2,3,4,5]);
print(vec1); // => [1,2,3,4,5]
print(vec1.sum().toString()); // => 15
Vector vec = Vector.fromList([1.0,2.0,3.0,4.0,5.0]); // works for double too.
print(vec.sum().toString()); // => 15

A solution that has worked cleanly for me is:
var total => [1,2,3,4].fold(0, (e, t) => e + t); // result 10

Different ways to find the sum of all dart list elements,
Method 1: Using a loop :
This is the most commonly used method. Iterate through the list using a loop and add all elements of the list to a final sum variable. We are using one for loop here :
main(List<String> args) {
var sum = 0;
var given_list = [1, 2, 3, 4, 5];
for (var i = 0; i < given_list.length; i++) {
sum += given_list[i];
}
print("Sum : ${sum}");
}
Method 2: Using forEach :
forEach is another way to iterate through a list. We can also use this method to find out the total sum of all values in a dart list. It is similar to the above method. The only difference is that we don’t have to initialize another variable i and list.length is not required.
main(List<String> args) {
var sum = 0;
var given_list = [1, 2, 3, 4, 5];
given_list.forEach((e) => sum += e);
print("Sum : ${sum}");
}
Method 3: Using reduce :
reduce method combines all elements of a list iteratively to one single value using a given function. We can use this method to find out the sum of all elements as like below :
main(List<String> args) {
var given_list = [1, 2, 3, 4, 5];
var sum = given_list.reduce((value, element) => value + element);
print("Sum : ${sum}");
}
Method 4: Using fold :
fold() is similar to reduce. It combines all elements of a list iteratively to one single value using a function. It takes one initial value and calculates the final value based on the previous value.
main(List<String> args) {
var sum = 0;
var given_list = [1,2,3,4,5];
sum = given_list.fold(0, (previous, current) => previous + current);
print("Sum : ${sum}");
}
for more details:https://www.codevscolor.com/dart-find-sum-list-elements

extension DoubleArithmeticExtensions on Iterable<double> {
double get sum => length == 0 ? 0 : reduce((a, b) => a + b);
}
extension IntArithmeticExtensions on Iterable<int> {
int get sum => length == 0 ? 0 : reduce((a, b) => a + b);
}
Usage:
final actual = lineChart.data.lineBarsData[0].spots.map((s) => s.x).sum;

Related

How to use the spread operator with ArrayList in kotlin?

I've read the documentation and I run into this issue of using the spread operator with an ArrayList Collection, and I want to know how to solve the mismatch type or implement a way to use it with ArrayList
I'll attach an image of the code along with the code.
fun howSum(targetSum: Int, numbers: ArrayList<Int>): ArrayList<Int>? {
if (targetSum == 0) return arrayListOf();
if (targetSum < 0) return null;
for (number: Int in numbers){
val remainder = targetSum - number;
val remainderResult = howSum(remainder, numbers);
if (remainderResult != null){
return arrayListOf(*remainderResult, number)
}
}
return null
}
Any comment could be helpful...
I think you need to give us more information about what you are trying to do for a better answer.
The spread operator is for passing an array in place of a varargs argument, but you can't add additional arguments to the array at the same time.
If you want a new ArrayList that contains the contents of another ArrayList with an extra element added, you can do something like this:
fun main() {
val foo = arrayListOf(1, 2, 3)
val bar = arrayListOf<Int>().apply {
addAll(foo)
add(4)
}
println(foo)
println(bar)
}
Output:
[1, 2, 3]
[1, 2, 3, 4]
But it's not efficient, because it copies all the items of foo into bar.
Spread operator is not applicable to Lists, it's intended only for arrays:
fun howSum(targetSum: Int, numbers: ArrayList<Int>): IntArray? {
if (targetSum == 0) return intArrayOf()
if (targetSum < 0) return null
for (number: Int in numbers) {
val remainder = targetSum - number;
val remainderResult = howSum(remainder, numbers);
if (remainderResult != null) {
return intArrayOf(*remainderResult, number)
}
}
return null
}
If you want to create new List of the other one with addition of some element, you can use + operator:
fun howSum(targetSum: Int, numbers: ArrayList<Int>): List<Int>? {
if (targetSum == 0) return arrayListOf();
if (targetSum < 0) return null;
for (number: Int in numbers){
val remainder = targetSum - number;
val remainderResult = howSum(remainder, numbers);
if (remainderResult != null){
return remainderResult + number
}
}
return null
}

Can we call joinpoint.proceed with arguments in Spring AOP

I am trying to call joinpoint.proceed with batches of arguments.
Is it possible to call.
I am not able to find any examples where we are partitioning the arguments or making new arguments then calling joinpoint.proceed on them.
Is this what you are looking for ?
#Service
public class AdditionService {
public Integer sum(List<Integer> list) {
Integer sum = 0;
for (Integer i : list) {
sum += i;
}
System.out.println("Sum :" + sum);
return sum;
}
}
and an aspect to find sum in batches
#Aspect
#Component
public class ExampleAspect {
#Around("execution(* com.package..*.sum*(..)) && within(com.package..*) && args(list)")
public Integer around(ProceedingJoinPoint pjp, List<Integer> list) throws Throwable {
Object[] args = pjp.getArgs(); // get the arguments array
Integer sum = 0;
for (int i = 0; i < 10; i += 5) {
args[0] = (list.subList(i, i + 5)); // modify the arguments array
System.out.println(args[0]);
sum += (Integer) pjp.proceed(args);
}
return sum;
}
}
the service bean accessed like following
Integer[] a= {1,2,3,4,5,6,7,8,9,10};
Integer sum = 0;
sum = service.sum(Arrays.asList(a));
System.out.println("Total : "+sum);
would print the following to console
[1, 2, 3, 4, 5]
Sum :15
[6, 7, 8, 9, 10]
Sum :40
Total : 55
Hope this helps

Kotlin - Convert while loop to functional style

I have the following Kotlin function:
fun func(n: Int): Int {
var count = 1
var m = n
while(m != 1) {
m = if(m.isOdd()) 3 * m + 1 else m / 2
count++
}
return count
}
I would like to write that simple algorithm in a "functional" style, using Kotlin's operators like map(), count(), etc. The closest thing I could come up with was this:
fun func(n: Int): Int {
return n.toList()
.map{ if(it.isOdd()) 3*it+1 else it/2 }
.takeWhile { it != 1 }
.count()
}
Obviously, the above code does not work because map is executed only once, but you get the idea of what I am trying to achieve.
PS: toList() is just an extension function that converts an int to a list containing that int:
fun Int.toList() = listOf(this)
Since you do not know how many items there will be, you can construct a (possibly infinite) sequence where each item is calculated based on the previous one, then limit it with your condition it != 1 and count how many items there are:
return generateSequence(n) { if (it.isOdd()) 3 * it + 1 else it / 2 }
.takeWhile { it != 1 }
.count()
Here, generateSequence(n) { ... }, constructs a Sequence<Int> that has n for its first element, and each of the following elements is calculated by the code passed as a lambda (it is called on the previous element, and only when another item is queried, i.e. lazily).

Comparator in binary search

I am not sure how to write comparator for Collectionos.binarySearch(). Can anyone help ? sample code:
List<Object> list1 = new ArrayList<>();
List<List<Object>> list2 = new ArrayList<>();
//loop starts
// adds elements into list1
list1.add(values);//values is an object containing elements like [3, John, Smith]
if (list2.size() == 0) {
list2.add(list1);//first element
} else {
if (index >= 0) {
int index = Collections.binarySearch(list2, list1, comparator);
list2.add(index, list1);//I want to add these elements in ascending order ?
}
}
//loop ends
How do I write comparator, so that elements in list 2 are added in ascending or descending order.
You can use an anonymous class which implements a Comparator<List<Object>>:
int index = Collections.binarySearch(list2, list1, new Comparator<List<Object>>() {
#Override
public int compare(List<Object> o1, List<Object> o2) {
// Your implementation here
return 0;
}
});
You could implement an IComparer<List<Object>> class, or use a lambda expression.
You just need to create a class that implements the Comparator interface.
For example, you can do this inline with an anonymous class:
Comparator<List<Object>> comparator = new Comparator<List<Object>>() {
#Override
public int compare(List<Object> x, List<Object> y) {
// custom logic to compare x and y here. Return a negative number
// if x < y, a positive number if x > y, and 0 otherwise
}
};
Collections.binarySearch(list, comparator);

What is the linq equivalent to the SQL IN operator

With linq I have to check if a value of a row is present in an array.
The equivalent of the sql query:
WHERE ID IN (2,3,4,5)
How can I do it?
.Contains
var resultset = from x in collection where new[] {2,3,4,5}.Contains(x) select x
Of course, with your simple problem, you could have something like:
var resultset = from x in collection where x >= 2 && x <= 5 select x
Perform the equivalent of an SQL IN with IEnumerable.Contains().
var idlist = new int[] { 2, 3, 4, 5 };
var result = from x in source
where idlist.Contains(x.Id)
select x;
db.SomeTable.Where(x => new[] {2,3,4,5}.Contains(x));
or
from x in db.SomeTable
where new[] {2,3,4,5}.Contains(x)
Intersect and Except are a little more concise and will probably be a bit faster too.
IN
collection.Intersect(new[] {2,3,4,5});
NOT IN
collection.Except(new[] {2,3,4,5});
or
Method syntax for IN
collection.Where(x => new[] {2,3,4,5}.Contains(x));
and NOT IN
collection.Where(x => !(new[] {2,3,4,5}.Contains(x)));
An IEnumerable<T>.Contains(T) statement should do what you're looking for.
A very basic example using .Contains()
List<int> list = new List<int>();
for (int k = 1; k < 10; k++)
{
list.Add(k);
}
int[] conditionList = new int[]{2,3,4};
var a = (from test in list
where conditionList.Contains(test)
select test);
The above situations work when the Contains function is used against primitives, but what if you are dealing with objects (e.g. myListOrArrayOfObjs.Contains(efObj))?
I found a solution! Convert your efObj into a string, thats separated by _ for each field (you can almost think of it as a CSV representation of your obj)
An example of such may look like this:
var reqAssetsDataStringRep = new List<string>();
foreach (var ra in onDemandQueueJobRequest.RequestedAssets)
{
reqAssetsDataStringRep.Add(ra.RequestedAssetId + "_" + ra.ImageId);
}
var requestedAssets = await (from reqAsset in DbContext.RequestedAssets
join image in DbContext.Images on reqAsset.ImageId equals image.Id
where reqAssetsDataStringRep.Contains(reqAsset.Id + "_" + image.Id)
select reqAsset
).ToListAsync();
You can write help-method:
public bool Contains(int x, params int[] set) {
return set.Contains(x);
}
and use short code:
var resultset = from x in collection
where Contains(x, 2, 3, 4, 5)
select x;
Following is a generic extension method that can be used to search a value within a list of values:
public static bool In<T>(this T searchValue, params T[] valuesToSearch)
{
if (valuesToSearch == null)
return false;
for (int i = 0; i < valuesToSearch.Length; i++)
if (searchValue.Equals(valuesToSearch[i]))
return true;
return false;
}
This can be used as:
int i = 5;
i.In(45, 44, 5, 234); // Returns true
string s = "test";
s.In("aa", "b", "c"); // Returns false
This is handy in conditional statements.