Comparator in binary search - 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);

Related

Assigning values to ArrayList using mapTo

Previously I was using this code:
private val mItems = ArrayList<Int>()
(1..item_count).mapTo(mItems) { it }
/*
mItems will be: "1, 2, 3, 4, 5, ..., item_count"
*/
Now, I am using a class instead of Int, but the class has Int member with name id.
class ModelClass(var id: Int = 0, var status: String = "smth")
So how can I use this method to fill the ArrayList in similar way?
//?
private val mItems = ArrayList<ModelClass>()
(1..item_count).mapTo(mItems) { mItems[position].id = it } // Something like this
//?
From the mapTo documentation:
Applies the given transform function to each element of the original collection and appends the results to the given destination.
Therefore, you just need to return the elements you want:
(1..item_count).mapTo(mItems) { ModelClass(it) }
If you are OK with any MutableList (which is often ArrayList or similar):
val mItems1 = MutableList(item_count) { i -> i }
val mItems2 = MutableList(item_count) { ModelClass(it) }

arrayList i only show the last element

I have the following problem. I'm trying to show all the elements of a display arrayList but I can only see the last item repeated as many times as there are number of elements in the ArrayList.
import java.util.ArrayList;
import java.util.Iterator;
public class PurebaArrayList {
public static void main(String[] args) {
ArrayList<PuntoDouble> puntos = new ArrayList<>();
PuntoDouble p = new PuntoDouble();
for(int cont = 0; cont< 100; cont++){
p.setX(cont);
p.setY(cont);
puntos.add(p);
}
System.out.println(puntos.toString());
}
}
public class PuntoDouble{
private double x;
private double y;
public PuntoDouble(double x, double y) {
this.x = x;
this.y = y;
}
public PuntoDouble(){
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
#Override
public String toString() {
return "PuntoDouble{" + "x=" + x + ", y=" + y + '}';
}
}
Thanks
You need to create a new PuntoDouble for every entry you add to the list. At the moment you add just a single instance of a PuntoDouble which you modify.
Therefore change the code to:
for(int cont = 0; cont< 100; cont++){
PuntoDouble p = new PuntoDouble();
p.setX(cont);
p.setY(cont);
puntos.add(p);
}
You are, literally, adding the same PuntoDouble as each of the 100 elements of the array. If you want them to be distinct from each other, you need to make a new one for each.
For debugging,slightly change 100 to 3 and add for each iteration to print out the elements in puntos.
// adds to ArrayList
for(int cont = 0; cont< 10; cont++){
p.setX(cont);
p.setY(cont);
System.out.println("[add]" + p);
puntos.add(p);
}
// iterates ArrayList puntos' elements
for(PuntoDouble pd : puntos){
System.out.println("[contain]" + pd);
}
debug output lines:
[add]PuntoDouble{x=0.0, y=0.0}
[add]PuntoDouble{x=1.0, y=1.0}
[add]PuntoDouble{x=2.0, y=2.0}
[add]PuntoDouble{x=3.0, y= 3.0}
[contain]PuntoDouble{x=9.0, y=9.0}
[contain]PuntoDouble{x=9.0, y=9.0}
[contain]PuntoDouble{x=9.0, y=9.0}
What you did is created an PuntoDouble object p and initilized it by invoking default constructor. In the for loop, the values of p modifies, but the reference of p never changed, therefore you kept adding the same object into ArrayList 100 times, all of those added objects refer to the same address in memory(new an object once before the for loop) which the value x is 99.0 and y is 99.0 (the last added values)
What you should do is creating a new object each iterate.
for(int cont = 0; cont< 100; cont++){
puntos.add(new PuntoDouble(cont, cont));
}

How to use GroupFormatter with ObjectListView control

I cannot seem to find anywhere, any examples on how to make use of the GroupFormatter delegate to allow me to add footers to my groups when using the ObjectListView control.
Does anyone have any examples that could demonstrate this? I want to remove the text from the group header and add a footer (different text per footer). As well as changing font, etc.
Any examples would be very helpful.
You can analyze the code for the
public void MakeGroupies<T>(T[] values, string[] descriptions, object[] images, string[] subtitles, string[] tasks)
method of the ObjectListView class. That explicitly sets the GroupKeyGetter, GroupKeyToTitleConverter and GroupFormatter property delegates.
This is C# but your VB adaptation should be straightforward. I am using this small test class as the object type to bind to the list view.
public class TestClass
{
private readonly string _s;
private readonly float _f;
public TestClass( string p1, float p2 )
{
this._s = p1;
this._f = p2;
}
[OLVColumn(DisplayIndex = 1, Name="S", Title="String")]
public string S {get {return this._s;}}
[OLVColumn( DisplayIndex = 2, Name = "F", Title = "Float" )]
public float F {get {return this._f;}}
}
So as not to manually define column traits I am using attributes inside the bound object and a
BrightIdeasSoftware.Generator.GenerateColumns( this.olv, typeof( TestClass ) );
call in the form/user control where I am using the list view. In fact here is the method that completely isolates ObjectListView configuration:
void SetData( TestClass[] objects )
{
// build list columns
Generator.GenerateColumns( this.olv, typeof( TestClass ) );
// use groups and make current column the priimary sort column
this.olv.ShowGroups = true;
this.olv.SortGroupItemsByPrimaryColumn = false;
// loop through columns and set properties
foreach( OLVColumn col in this.olv.Columns )
{
col.Groupable = true;
col.Sortable = true;
if( col.Name == "F" )
{
col.MakeGroupies<float>( new float[] { 10f, 100f, 1000f }, new string[] { "<10", "10-100", "100-1000", ">1000" } );
}
else if( col.Name == "S" )
{
col.UseInitialLetterForGroup = false;
//
col.GroupKeyGetter = ( obj ) =>
{
TestClass tc = (TestClass)obj;
switch( char.ToLower( tc.S[0] ) )
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u': return true;
default: return false;
}
};
//
col.GroupKeyToTitleConverter = ( o ) => { bool b = (bool)o; return b ? "vowel" : "consonant"; };
//
col.GroupFormatter = ( /*OLVGroup*/ group, /*GroupingParameters*/ parms ) =>
{
string s = string.Format ("{0} {1}", group.GroupId, group.Id);
//group.BottomDescription = "BottomDescription: " + s;
//group.TopDescription = "TopDescription: " + s;
group.Footer = "Footer: " + s;
};
}
}
//
this.olv.RebuildColumns();
//
this.olv.SetObjects( objects );
}
You will definitely have one different footer per each group.

JUnit testing method with assertions

The isSorted() instance method in class A has a bug:
public class A {
private int[] a;
public A(int[] a) { this.a = a; }
/** Return true if this A object contains an array sorted
* in nondecreasing order; else false. */
public boolean isSorted() {
for(int i=1; i<a.length-1; i++) {
if(a[i] < a[i-1]) return false;
}
return true;
}
}
Write a JUnit test method testIsSorted() which will fail because of this bug, but will pass when the bug is fixed.
(Assume that there is no setUp() method defined.)
This is the answer:
public void testIsSorted() {
int[] array = {2, 1};
A haha = new A(array);
assertFalse(haha.isSorted);
}
first of all where is the bug, i cannot seem to located it.
Secondly shoudn't it be assertTrue(haha.isSorted)
because when its assertFalse it will pass because the array is in descending order, therefore the isSorted will return false and assertFalse(false) will return true where-as assertTrue(false) will return false.
The bug is on the line
for(int i=1; i<a.length-1; i++) {
Since array indexes start at 0, the definition of i should be int i=0, not 1. The index 1 points to the second element of the array.
The assertFalse statement checks that the isSorted() method returns false for the given array {2,1}. The isSorted() method checks that no entry is less than the previous one (conversely, each entry is greater than or equal to the previous one). In the example, it will return false, because 2 at index 0 is greater than 1 at index 1. Therefore, the assertFalse is the correct assertion for the case.
You could also test like this (note the reversed order of array).
public void testIsSorted() {
int[] array = {1, 2};
A haha = new A(array);
assertTrue(haha.isSorted());
}

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

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;