I need to create a multidemensional ArrayList to hold String values. I know how to do this with a standard array, like so: public static String[][] array = {{}} but this is no good because I don't know the size of my array, all I know is how many dimensions it will have.
How can I make a 'dynamically resizable array with 2/+ demensions'?
Edit/Update
Maybe it would be easier to resize or define a standard array using a varible? But I don't know?
It's probably easier to use my original idea of an ArrayList though... All I need is a complete example code to create a 2D ArrayList and add so example values to both dimensions without knowing the index.
ArrayList<ArrayList<String>> array = new ArrayList<ArrayList<String>>();
Depending on your requirements, you might use a Generic class like the one below to make access easier:
import java.util.ArrayList;
class TwoDimentionalArrayList<T> extends ArrayList<ArrayList<T>> {
public void addToInnerArray(int index, T element) {
while (index >= this.size()) {
this.add(new ArrayList<T>());
}
this.get(index).add(element);
}
public void addToInnerArray(int index, int index2, T element) {
while (index >= this.size()) {
this.add(new ArrayList<T>());
}
ArrayList<T> inner = this.get(index);
while (index2 >= inner.size()) {
inner.add(null);
}
inner.set(index2, element);
}
}
If you're allowed to use predefined Java classes, you could do something like:
private static ArrayList<ArrayList<String>> biDemArrList = new ArrayList<ArrayList<String>>();
Then you can add new elements, something like:
ArrayList<String> temp = new ArrayList<String>(); // added ()
temp.add("Hello world.");
biDemArrList.add(temp);
Hope you can understand what I mean and what's going on. Also, you'll need to import java.util.ArrayList; for this, if you're making use of the Java class.
ArrayList<ArrayList<String>>
http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html
http://en.wikipedia.org/wiki/Generics_in_Java
Once I required 2-D arrayList and I created using List and ArrayList and the code is as follows:
import java.util.*;
public class ArrayListMatrix {
public static void main(String args[]){
List<ArrayList<Integer>> a = new ArrayList<>();
ArrayList<Integer> a1 = new ArrayList<Integer>();
ArrayList<Integer> a2 = new ArrayList<Integer>();
ArrayList<Integer> a3 = new ArrayList<Integer>();
a1.add(1);
a1.add(2);
a1.add(3);
a2.add(4);
a2.add(5);
a2.add(6);
a3.add(7);
a3.add(8);
a3.add(9);
a.add(a1);
a.add(a2);
a.add(a3);
for(ArrayList obj:a){
ArrayList<Integer> temp = obj;
for(Integer job : temp){
System.out.print(job+" ");
}
System.out.println();
}
}
}
Output:
1 2 3
4 5 6
7 8 9
Source : https://www.codepuran.com/java/2d-matrix-arraylist-collection-class-java/
I can think of An Array inside an Array or a Guava's MultiMap?
e.g.
ArrayList<ArrayList<String>> matrix = new ArrayList<ArrayList<String>>();
You can have ArrayList with elements which would be ArrayLists itself.
Wouldn't List<ArrayList<String>> 2dlist = new ArrayList<ArrayList<String>>(); be a better (more efficient) implementation?
Here an answer for those who'd like to have preinitialized lists of lists. Needs Java 8+.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class Scratch {
public static void main(String[] args) {
int M = 4;
int N = 3;
// preinitialized array (== list of lists) of strings, sizes not fixed
List<List<String>> listOfListsOfString = initializeListOfListsOfT(M, N, "-");
System.out.println(listOfListsOfString);
// preinitialized array (== list of lists) of int (primitive type), sizes not fixed
List<List<Integer>> listOfListsOfInt = initializeListOfListsOfInt(M, N, 7);
System.out.println(listOfListsOfInt);
}
public static <T> List<List<T>> initializeListOfListsOfT(int m, int n, T initValue) {
return IntStream
.range(0, m)
.boxed()
.map(i -> new ArrayList<T>(IntStream
.range(0, n)
.boxed()
.map(j -> initValue)
.collect(Collectors.toList()))
)
.collect(Collectors.toList());
}
public static List<List<Integer>> initializeListOfListsOfInt(int m, int n, int initValue) {
return IntStream
.range(0, m)
.boxed()
.map(i -> new ArrayList<>(IntStream
.range(0, n)
.map(j -> initValue)
.boxed()
.collect(Collectors.toList()))
)
.collect(Collectors.toList());
}
}
Output:
[[-, -, -], [-, -, -], [-, -, -], [-, -, -]]
[[7, 7, 7], [7, 7, 7], [7, 7, 7], [7, 7, 7]]
Side note for those wondering about IntStream:
IntStream
.range(0, m)
.boxed()
is equivalent to
Stream
.iterate(0, j -> j + 1)
.limit(n)
Credit goes for JAcob Tomao for the code.
I only added some comments to help beginners like me understand it.
I hope it helps.
// read about Generic Types In Java & the use of class<T,...> syntax
// This class will Allow me to create 2D Arrays that do not have fixed sizes
class TwoDimArrayList<T> extends ArrayList<ArrayList<T>> {
public void addToInnerArray(int index, T element) {
while (index >= this.size()) {
// Create enough Arrays to get to position = index
this.add(new ArrayList<T>()); // (as if going along Vertical axis)
}
// this.get(index) returns the Arraylist instance at the "index" position
this.get(index).add(element); // (as if going along Horizontal axis)
}
public void addToInnerArray(int index, int index2, T element) {
while (index >= this.size()) {
this.add(new ArrayList<T>());// (as if going along Vertical
}
//access the inner ArrayList at the "index" position.
ArrayList<T> inner = this.get(index);
while (index2 >= inner.size()) {
//add enough positions containing "null" to get to the position index 2 ..
//.. within the inner array. (if the requested position is too far)
inner.add(null); // (as if going along Horizontal axis)
}
//Overwrite "null" or "old_element" with the new "element" at the "index 2" ..
//.. position of the chosen(index) inner ArrayList
inner.set(index2, element); // (as if going along Horizontal axis)
}
}
What would you think of this for 3D ArrayList - can be used similarly to
arrays - see the comments in the code:
import java.util.ArrayList;
import java.util.List;
/**
* ArrayList3D simulates a 3 dimensional array,<br>
* e.g: myValue = arrayList3D.get(x, y, z) is the same as: <br>
* myValue = array[x][y][z] <br>
* and<br>
* arrayList3D.set(x, y, z, myValue) is the same as:<br>
* array[x][y][z] = myValue; <br>
* but keeps its full ArrayList functionality, thus its
* benefits of ArrayLists over arrays.<br>
* <br>
* #param <T> data type
*/
public class ArrayList3D <T> {
private final List<List<List<T>>> arrayList3D;
public ArrayList3D() {
arrayList3D = newArrayDim1();
}
/**
* Get value of the given array element.<br>
* E.g: get(2, 5, 3);<br>
* For 3 dim array this would equal to:<br>
* nyValue = array[2][5][3];<br>
* <br>
* Throws: IndexOutOfBoundsException
* - if any index is out of range
* (index < 0 || index >= size())<br>
* <br>
* #param dim1 index of the first dimension of the array list
* #param dim2 index of the second dimension of the array list
* #param dim3 index of the third dimension of the array list
* #return value of the given array element (of type T)
*/
public T get(int dim1, int dim2, int dim3) {
List<List<T>> ar2 = arrayList3D.get(dim1);
List<T> ar3 = ar2.get(dim2);
return ar3.get(dim3);
}
/**
* Set value of the given array.<br>
* E.g: set(2, 5, 3, "my value");<br>
* For 3 dim array this would equal to:<br>
* array[2][5][3]="my value";<br>
* <br>
* Throws: IndexOutOfBoundsException
* - if any index is out of range
* (index < 0 || index >= size())<br>
* <br>
* #param dim1 index of the first dimension of the array list
* #param dim2 index of the second dimension of the array list
* #param dim3 index of the third dimension of the array list
* #param value value to assign to the given array
* <br>
*/
public void set(int dim1, int dim2, int dim3, T value) {
arrayList3D.get(dim1).get(dim2).set(dim3, value);
}
/**
* Set value of the given array element.<br>
* E.g: set(2, 5, 3, "my value");<br>
* For 3 dim array this would equal to:<br>
* array[2][5][3]="my value";<br>
* <br>
* Throws: IndexOutOfBoundsException
* - if any index is less then 0
* (index < 0)<br>
* <br>
* #param indexDim1 index of the first dimension of the array list
* #param indexDim2 index of the second dimension of the array list
* If you set indexDim1 or indexDim2 to value higher
* then the current max index,
* the method will add entries for the
* difference. The added lists will be empty.
* #param indexDim3 index of the third dimension of the array list
* If you set indexDim3 to value higher
* then the current max index,
* the method will add entries for the
* difference and fill in the values
* of param. 'value'.
* #param value value to assign to the given array index
*/
public void setOrAddValue(int indexDim1,
int indexDim2,
int indexDim3,
T value) {
List<T> ar3 = setOrAddDim3(indexDim1, indexDim2);
int max = ar3.size();
if (indexDim3 < 0)
indexDim3 = 0;
if (indexDim3 < max)
ar3.set(indexDim3, value);
for (int ix = max-1; ix < indexDim3; ix++ ) {
ar3.add(value);
}
}
private List<List<List<T>>> newArrayDim1() {
List<T> ar3 = new ArrayList<>();
List<List<T>> ar2 = new ArrayList<>();
List<List<List<T>>> ar1 = new ArrayList<>();
ar2.add(ar3);
ar1.add(ar2);
return ar1;
}
private List<List<T>> newArrayDim2() {
List<T> ar3 = new ArrayList<>();
List<List<T>> ar2 = new ArrayList<>();
ar2.add(ar3);
return ar2;
}
private List<T> newArrayDim3() {
List<T> ar3 = new ArrayList<>();
return ar3;
}
private List<List<T>> setOrAddDim2(int indexDim1) {
List<List<T>> ar2 = null;
int max = arrayList3D.size();
if (indexDim1 < 0)
indexDim1 = 0;
if (indexDim1 < max)
return arrayList3D.get(indexDim1);
for (int ix = max-1; ix < indexDim1; ix++ ) {
ar2 = newArrayDim2();
arrayList3D.add(ar2);
}
return ar2;
}
private List<T> setOrAddDim3(int indexDim1, int indexDim2) {
List<List<T>> ar2 = setOrAddDim2(indexDim1);
List<T> ar3 = null;
int max = ar2.size();
if (indexDim2 < 0)
indexDim2 = 0;
if (indexDim2 < max)
return ar2.get(indexDim2);
for (int ix = max-1; ix < indexDim2; ix++ ) {
ar3 = newArrayDim3();
ar2.add(ar3);
}
return ar3;
}
public List<List<List<T>>> getArrayList3D() {
return arrayList3D;
}
}
And here is a test code:
ArrayList3D<Integer> ar = new ArrayList3D<>();
int max = 3;
for (int i1 = 0; i1 < max; i1++) {
for (int i2 = 0; i2 < max; i2++) {
for (int i3 = 0; i3 < max; i3++) {
ar.setOrAddValue(i1, i2, i3, (i3 + 1) + (i2*max) + (i1*max*max));
int x = ar.get(i1, i2, i3);
System.out.println(" - " + i1 + ", " + i2 + ", " + i3 + " = " + x);
}
}
}
Result output:
0, 0, 0 = 1
0, 0, 1 = 2
0, 0, 2 = 3
0, 1, 0 = 4
0, 1, 1 = 5
0, 1, 2 = 6
0, 2, 0 = 7
0, 2, 1 = 8
0, 2, 2 = 9
1, 0, 0 = 10
1, 0, 1 = 11
1, 0, 2 = 12
1, 1, 0 = 13
1, 1, 1 = 14
1, 1, 2 = 15
1, 2, 0 = 16
1, 2, 1 = 17
1, 2, 2 = 18
2, 0, 0 = 19
2, 0, 1 = 20
2, 0, 2 = 21
2, 1, 0 = 22
2, 1, 1 = 23
2, 1, 2 = 24
2, 2, 0 = 25
2, 2, 1 = 26
2, 2, 2 = 27
You can also do something like this ...
First create and Initialize the matrix or multidimensional arraylist
ArrayList<ArrayList<Integer>> list;
MultidimentionalArrayList(int x,int y)
{
list = new ArrayList<>();
for(int i=0;i<=x;i++)
{
ArrayList<Integer> temp = new ArrayList<>(Collections.nCopies(y+1,0));
list.add(temp);
}
}
Add element at specific position
void add(int row,int column,int val)
{
list.get(row).set(column,val); // list[row][column]=val
}
This static matrix can be change into dynamic if check that row and
column are out of bound. just insert extra temp arraylist for row
remove element
int remove(int row, int column)
{
return list.get(row).remove(column);// del list[row][column]
}
ArrayList<ArrayList<Integer>> C = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> a = new ArrayList<Integer>();
a.addAll(Arrays.asList(7, 3));
ArrayList<Integer> b = new ArrayList<Integer>();
b.addAll(Arrays.asList(2, 1));
ArrayList<Integer> c = new ArrayList<Integer>();
c.addAll(Arrays.asList(4, 9));
C.addAll(Arrays.asList(a, b, c));
C.forEach(System.out::print);
You can simply use:
ArrayList<ArrayList<T>> multiDimentionalArray = new ArrayList<ArrayList<T>>();
You can change T to whatever data type you need
Related
I have a list that has some elements, I need to print the first 3 elements when page num = 1,
then next 3 elements when page ==2 likewise
public class OtherTemporaryTrials {
public static void main(String[] args) {
int numOfPages = 6;
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(13);
al.add(77);
al.add(53);
al.add(63);
al.add(173);
al.add(134);
al.add(1366);
al.add(13446);
al.add(1333);
al.add(1323);
al.add(163);
al.add(1335);
al.add(13228);
al.add(1573);
al.add(13355);
al.add(12343);
al.add(12353);
for(int i=0;i<numOfPages;i++) {
setdata(al,numOfPages);
}
}
private static void setdata(ArrayList<Integer> al, int numOfPages) {
for(int i=0;i<3;i++) {
// Here for every next page we should get the next 3 elements from List
System.out.println(al.get(i));
}
}
}
To access the nth page with a page size of k, you need to get the elements in the range n * k to (n + 1) * k. This is easily done using the subList API:
public class Main {
public static List<Integer> getPage(List<Integer> list, int pageSize, int pageNo) {
// get the from & to range bounds, respecting the list length to prevent IndexOutOfBound exceptions
int from = pageNo * pageSize;
int to = Math.min(list.size(), (pageNo + 1) * pageSize);
// return the expected slice of the list
return list.subList(from, to);
}
public static void clearPage(List<Integer> list, int pageSize, int pageNo) {
// get the from & to range bounds, respecting the list length to prevent IndexOutOfBound exceptions
int from = pageNo * pageSize;
int to = Math.min(list.size(), (pageNo + 1) * pageSize);
// clear the expected slice from the list
// this is allowed as long as the list is not "read-only"
list.subList(from, to).clear();
}
public static void main(String[] args) {
// need to use an array list because Arrays.asList return an immutable list (read-only)
var list = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
int pageSize = 3;
// print pages
System.out.println(getPage(list, pageSize, 0));
System.out.println(getPage(list, pageSize, 1));
System.out.println(getPage(list, pageSize, 2));
System.out.println(getPage(list, pageSize, 3));
System.out.println(list);
// delete elements at position 0 to 2
clearPage(list, pageSize, 0);
System.out.println(list);
// delete elements at position 3 to 5
clearPage(list, pageSize, 1);
System.out.println(list);
}
}
Because this works with zero-based indices, if you want 1 to represent the first page, you need to substract 1 from the page number before using it to calculate the range bounds of subList.
I have code for a MergeSort of generic arrays. The only problem is, that I want the output to be with the index instead of the actual int, float or whatever. Do you guys have any idea on how to do that?
Here is the code I have so far:
class MergeSortGeneric<T extends Comparable<? super T>> {
public static void main(String[] args)
{
// example using Strings
String[] arrayOfStrings = {"Andree", "Leana", "Faviola", "Loyce", "Quincy",
"Milo", "Jamila", "Toccara", "Nelda", "Blair", "Ernestine", "Chara", "Kareen", "Monty", "Rene",
"Cami", "Winifred", "Tara", "Demetrice", "Azucena"};
MergeSortGeneric<String> stringSorter = new MergeSortGeneric<>();
stringSorter.mergeSort(arrayOfStrings, 0, arrayOfStrings.length - 1);
System.out.println(java.util.Arrays.toString(arrayOfStrings));
// example using Doubles
Double[] arrayOfDoubles = {0.35, 0.02, 0.36, 0.82, 0.27, 0.49, 0.41, 0.17, 0.30,
0.89, 0.37, 0.66, 0.82, 0.17, 0.20, 0.96, 0.18, 0.25, 0.37, 0.52};
MergeSortGeneric<Double> doubleSorter = new MergeSortGeneric<>();
doubleSorter.mergeSort(arrayOfDoubles, 0, arrayOfDoubles.length - 1);
System.out.println(java.util.Arrays.toString(arrayOfDoubles));
}
// main function that sorts array[start..end] using merge()
void mergeSort(T[] array, int start, int end)
{
// base case
if (start < end)
{
// find the middle point
int middle = (start + end) / 2;
mergeSort(array, start, middle); // sort first half
mergeSort(array, middle + 1, end); // sort second half
// merge the sorted halves
merge(array, start, middle, end);
}
}
// merges two subarrays of array[].
void merge(T[] array, int start, int middle, int end)
{
T[] leftArray = (T[]) new Comparable[middle - start + 1];
T[] rightArray = (T[]) new Comparable[end - middle];
// fill in left array
for (int i = 0; i < leftArray.length; ++i)
leftArray[i] = array[start + i];
// fill in right array
for (int i = 0; i < rightArray.length; ++i)
rightArray[i] = array[middle + 1 + i];
/* Merge the temp arrays */
// initial indexes of first and second subarrays
int leftIndex = 0, rightIndex = 0;
// the index we will start at when adding the subarrays back into the main array
int currentIndex = start;
// compare each index of the subarrays adding the lowest value to the currentIndex
while (leftIndex < leftArray.length && rightIndex < rightArray.length)
{
if (leftArray[leftIndex].compareTo(rightArray[rightIndex]) <= 0)
{
array[currentIndex] = leftArray[leftIndex];
leftIndex++;
}
else
{
array[currentIndex] = rightArray[rightIndex];
rightIndex++;
}
currentIndex++;
}
// copy remaining elements of leftArray[] if any
while (leftIndex < leftArray.length) array[currentIndex++] = leftArray[leftIndex++];
// copy remaining elements of rightArray[] if any
while (rightIndex < rightArray.length) array[currentIndex++] = rightArray[rightIndex++];
}
}
thank you guys for any tips. Thats the task by the way:
Implement the Merge-Sort algorithm. The algorithm sorts a java.util.list
of any elements. Therefore the class must be generic. For sorting it gets a
matching comparator.
var data = Arrays.asList(23, 42, 11, 1, 12);
var mergeSort = new MergeSort<Integer>();
mergeSort.setup(data, (i1, i2) -> i1 - i2);
However, the element positions in the input list are not changed. Instead, the
specifies the sorting by a permutation array. The array has as many in-elements as
the input data list has elements. Each τ element specifies the index of the corresponding input element after sorting. Also internally you use only permutation arrays and no
further lists of input elements.
The easiest way without modifying the merge algorithm you be:
Create a copy of the arrays to be sorted;
Sort the arrays;
Compare the copy and the sorted array and figure it out the index.
For example:
String[] arrayOfStrings = {...};
List<String> copyArrayOfStrings = Arrays.stream(arrayOfStrings).collect(Collectors.toList());
...
stringSorter.mergeSort(arrayOfStrings, 0, arrayOfStrings.length - 1);
...
List<Integer> index = Arrays.stream(arrayOfStrings).map(copyArrayOfStrings::indexOf).collect(Collectors.toList());
System.out.println(java.util.Arrays.toString(index.toArray()));
If for some strange reason you can only use arrays, and basic operators, the aforementioned logic still holds true:
the copy:
String[] copyArrayOfStrings = new String[arrayOfStrings.length];
for(int i = 0; i < arrayOfStrings.length; i++){
copyArrayOfStrings[i] = arrayOfStrings[i];
}
the sorting:
stringSorter.mergeSort(arrayOfStrings, 0, arrayOfStrings.length - 1);
getting the indexes:
Integer[] index = new Integer[copyArrayOfStrings.length];
int index_pos = 0;
for(String s : arrayOfStrings) {
for (int i = 0; i < copyArrayOfStrings.length; i++) {
if(copyArrayOfStrings[i].equals(s)){
index[index_pos++] = i;
break;
}
}
}
System.out.println(java.util.Arrays.toString(index));
You can use a lambda compare, if the indexes are Integer types as opposed to native ints. Only the array of indices needs to be Integer type, the array of values can be primitive type.
package x;
import java.util.Arrays;
public class x {
public static void main(String[] args) {
int[] A = {3, 1, 2, 0};
Integer[] I = {0, 1, 2, 3};
Arrays.sort(I, (i, j) -> A[i]-A[j]);
for (Integer i : I) {
System.out.println(A[i]);
}
}
}
you can create a class like below (note it is pseudo code)
import java.util.Arrays;
public class SomeClass {
public static void main(String[] args) {
double[] doubleArray = new double[] {2.3, 3.4, 1.2, 0.3, 4.3};
ObjectWithIndex[] objectWithIndexAr = new ObjectWithIndex[doubleArray.length];
for (int i = 0; i < doubleArray.length; i++) {
objectWithIndexAr[i] = new ObjectWithIndex(i, doubleArray[i]);
}
Arrays.sort(objectWithIndexAr);
for ( ObjectWithIndex obj : objectWithIndexAr) {
System.out.println("index: " + obj.index + " value: " + obj.actualObject);
}
}
}
class ObjectWithIndex implements Comparable<ObjectWithIndex> {
int index;
Comparable actualObject;
public ObjectWithIndex(int index, Comparable object) {
this.index = index;
this.actualObject = object;
}
#Override
public int compareTo(ObjectWithIndex o) {
return this.actualObject.compareTo(o.actualObject);
}
}
you can create array of this object using your input array of Double, Integer (whatever implements Comparable) and sort the new array of ObjectWithIndex.
once sorted, you can print the index (which will have original index from your input)
I want to use partition function of Opencv in Java wrapper. But I can not find it's package.
Edit
This is an open issue on opencv. Is there any alternative?
I know this question is about half a year old, but i recently came across this question when searching for opencv partitioning. This method is still not implemented in Java, so i copied the C++ code and changed it a bit to compile in Java. Here it is:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.function.BiPredicate;
public class Partition {
public static void main(String[] args) {
List<String> list = new LinkedList<>(Arrays.asList("aa", "ab", "aa", "bb", "bb", "a", "b", "a", "b", "b"));
List<Integer> list2 = new ArrayList<>(Arrays.asList(1, 2, 10, 11, 10, 42, 3, 2, 3));
List<Integer> labels = new ArrayList<>();
int classes = partition(list, labels);
System.out.println("There are " + classes + " classes of equal strings:");
System.out.println(labels);
classes = partition(list2, labels);
System.out.println("There are " + classes + " classes of equal integers:");
System.out.println(labels);
classes = partition(list, labels, (str1, str2) -> str1.length() == str2.length());
System.out.println("There are " + classes + " classes of strings with same length:");
System.out.println(labels);
classes = partition(list2, labels, (i1, i2) -> Math.abs(i1-i2) <= 1);
System.out.println("There are " + classes + " classes of integers within 1 range:");
System.out.println(labels);
}
/**
* Overloaded method with default equality predicate
*
* #param _vec vector of elements to be partitioned
* #param labels output list of labels
* #return number of classes
*/
public static <E> int partition(final List<E> _vec, List<Integer> labels) {
return partition(_vec, labels, E::equals);
}
/**
* Port of C++ partition function
*
* #param _vec list of elements to be partitioned
* #param labels output list of labels
* #param predicate predicate to test whether two elements belong to the same class
* #return number of classes
* #see https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/operations.hpp
* #see https://docs.opencv.org/2.4/modules/core/doc/clustering.html
*/
//template<typename _Tp, class _EqPredicate> int
//partition( const std::vector<_Tp>& _vec, std::vector<int>& labels,
// _EqPredicate predicate=_EqPredicate())
public static <E> int partition(final List<E> _vec, List<Integer> labels, BiPredicate<E, E> predicate)
{
int i, j, N = (int)_vec.size();
//const _Tp* vec = &_vec[0];
final ArrayList<E> vec = new ArrayList<>(_vec);
final int PARENT=0;
final int RANK=1;
//std::vector<int> _nodes(N*2);
//int (*nodes)[2] = (int(*)[2])&_nodes[0];
int[][] nodes = new int[N*2][2];
// The first O(N) pass: create N single-vertex trees
for(i = 0; i < N; i++)
{
nodes[i][PARENT]=-1;
nodes[i][RANK] = 0;
}
// The main O(N^2) pass: merge connected components
for( i = 0; i < N; i++ )
{
int root = i;
// find root
while( nodes[root][PARENT] >= 0 )
root = nodes[root][PARENT];
for( j = 0; j < N; j++ )
{
//if( i == j || !predicate(vec[i], vec[j]))
if(i == j || !predicate.test(vec.get(i), vec.get(j)))
continue;
int root2 = j;
while( nodes[root2][PARENT] >= 0 )
root2 = nodes[root2][PARENT];
if( root2 != root )
{
// unite both trees
int rank = nodes[root][RANK], rank2 = nodes[root2][RANK];
if( rank > rank2 )
nodes[root2][PARENT] = root;
else
{
nodes[root][PARENT] = root2;
nodes[root2][RANK] += (rank == rank2 ? 1 : 0);
root = root2;
}
//CV_Assert( nodes[root][PARENT] < 0 );
assert(nodes[root][PARENT] < 0);
int k = j, parent;
// compress the path from node2 to root
while( (parent = nodes[k][PARENT]) >= 0 )
{
nodes[k][PARENT] = root;
k = parent;
}
// compress the path from node to root
k = i;
while( (parent = nodes[k][PARENT]) >= 0 )
{
nodes[k][PARENT] = root;
k = parent;
}
}
}
}
// Final O(N) pass: enumerate classes
//labels.resize(N);
Integer[] _labels = new Integer[N];
int nclasses = 0;
for( i = 0; i < N; i++ )
{
int root = i;
while( nodes[root][PARENT] >= 0 )
root = nodes[root][PARENT];
// re-use the rank as the class label
if( nodes[root][RANK] >= 0 )
nodes[root][RANK] = ~nclasses++;
_labels[i] = ~nodes[root][RANK];
}
labels.clear();
labels.addAll(Arrays.asList(_labels));
return nclasses;
}
}
Output is as follows:
There are 5 classes of equal strings:
[0, 1, 0, 2, 2, 3, 4, 3, 4, 4]
There are 6 classes of equal integers:
[0, 1, 2, 3, 2, 4, 5, 1, 5]
There are 2 classes of strings with same length:
[0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
There are 3 classes of integers within 1 range:
[0, 0, 1, 1, 1, 2, 0, 0, 0]
I tried to leave as much original code as possible and commented out lines which i had to change. To see the original code (in C++), you may want to look here. The documentation can be found here.
I have this array :
int[][] multi = new int[][]{
{ 3, 4, 2},
{ 2, 2, 5 },
{ 1, 2 }
};
I would like to print the produce of each cells. It's pretty hard to explain so lets see some example :
For my table i need to print :
6 //(3*2*1)
12 //(3*2*2)
6 //(3*2*1)
12 //(3*2*2)
15 //(3*5*1)
30 //(3*5*2)
8 //(4*2*1)
16 //(4*2*2)
8 //(4*2*1)
16 //(4*2*2)
20 //(4*5*1)
40 //(4*5*2)
...
Size of table can change, i need a generic things.
Here is my start but it's not doing what i need. This is looping line by line...
for (int i = 0; i<multi[0].length; i++) {
for (int k = 0; k < multi.length; k++) {
for (int l = 0; l < multi[k].length; l++ ) {
System.err.println(multi[k][l]);
}
}
}
I thing you have to do that recursively if your dimensions of array is not fixed..
I came up the code for dynamic dimension of 2D array
public class HelloWorld{
static int[][] multi = new int[][]{
{ 3, 4, 2},
{ 2, 2, 5 },
{ 1, 2 }
};
static public void pattern(int row,int multip) {
if(row >= multi.length) {
System.out.println(multip);
return ;
}
for(int i = 0; i<multi[row].length;i++) {
multip*=multi[row][i];
row+=1;
pattern(row,multip);
row-=1;
multip/=multi[row][i];
}
}
public static void main(String []args){
pattern(0,1);
}
}
If your dimensions are fixed then you can also do that using above logic but for that if you want to do iterative then you have to repeatedly create loops inside loop.
It's not hard to explain if you use mathematics terms and what you need is simply a Cartesian product of the sets (i.e. each row) in your bidimensional array.
It could be a bit longer to explain here the theory about Cartesian product (X is the operator) but in practice you have to calculate the result of:
((multi[0] X multi[1]) X ...) X multi[n]
And you ends with a bidimensional array with a number of rows which is the product of all the cardinality of each set and each row has a number of elements which is the number of the sets (because each tupla has an element from each set).
Another thing is that the tuple are ordered i.e. the element of a set will be in the same position in all the tuples e.g. each tupla in position 0 will have an element of multi[0].
Knowing these properties is possible to create the product with a construction algorithm which puts the elements of the first set in the first column of the resulting set repeating them the necessary amount of time and then go on with the next set/next column.
At the end when you have your Cartesian product you can do anything you want e.g. calculate the product of the elements of each row.
public class CartesianProductProduct {
public int[][] product(int[][] sets) {
int cardinality = 1;
for (int is = 0; is < sets.length; is++) cardinality *= sets[is].length;
int[][] cartesianProduct = new int[cardinality][sets.length];
int curCardinality = 1;
for (int is = 0; is < sets.length; is++) {
curCardinality *= sets[is].length;
int repetition = cardinality / curCardinality;
int ie = 0;
for (int ic = 0; ic < cardinality; ic++) {
cartesianProduct[ic][is] = sets[is][ie];
if (repetition == 1) {
ie++;
} else if ((ic + 1) % repetition == 0) {
ie++;
}
ie = ie == sets[is].length ? 0 : ie;
}
}
return cartesianProduct;
}
public static void main(String[] args) {
int[][] multi = new int[][]{
{3, 4, 2},
{2, 2, 5},
{1, 2}
};
int[][] cartesianProduct = new CartesianProductProduct().product(multi);
for (int i = 0; i < cartesianProduct.length; i++) {
int prod = 1;
String s = "";
String sep = "";
for (int k = 0; k < cartesianProduct[i].length; k++) {
prod *= cartesianProduct[i][k];
s = s + sep + cartesianProduct[i][k];
sep = "*";
}
System.out.printf("%s //(%s)\n", prod, s);
}
}
}
I have an array of objects, let's say each object is of a type Grid.
Each Grid object has x and y coordinates,
Grid temp = new Grid(3, 5);
// temp.x returns x, temp.y returns y.
Now I have a few arrays of Grid
Grid[] theArray1 = new Grid[5];
Grid[] theArray2 = new Grid[5];
Grid[] theArray3 = new Grid[5];
I fill the arrays up with Grid objects and sort them using Arrays.sort.
I now join the sorted arrays to form theArray with length 5+5+5=15.
I now want to sort theArray by the first element of the "subarrays" (elements 0, 5 and 10 in theArray)
How could I achive this? Also, if there is a simpler way to achieve the same result, that would be nice. But I have to start with the 3 arrays since they are gotten through an iteration of a for-loop.
EDIT:
Example: Let's say I sort by X coordinated, smaller first.
I'll make each Grid[] of length 3 instead of 5 for simplicity.
Grid[] theArray1 = new Grid[]{new Grid(2, 1), new Grid(4, 1), new Grid(0, 1)};
Grid[] theArray2 = new Grid[]{new Grid(4, 2), new Grid(3, 1), new Grid(7, 1)};
Grid[] theArray3 = new Grid[]{new Grid(1, 7), new Grid(5, 3), new Grid(10, 1)};
What I want to end up with is an array/arraylist that, when printed, prints like this:
for (int i = 0; i <= theArray.length-2; i++) {
StdOut.println(theArray[i] + ", " + theArray[i+1] + ", " + theArray[i+2] + "\n");
}
// Output:
(0, 1), (2, 1), (4, 1) //this is theArray1
(1, 7), (5, 3), (10, 1) //this is theArray3
(3, 1), (4, 2), (7, 1) //this is theArray2
First I sort each theArray(1, 2 and 3) so that the element with the lowest x coordinate is first, then second smallest, then largest.
Then I arrange these arrays by the size of the first element of each of them. theArray3 goes before theArray2 because the x coordinate of the first element is 1 but 3 in theArray2
Assuming Grid implements Comparable<Grid>, sort each array and add to 2d-array. Then sort that array of arrays of grids using Arrays.sort(Grid[][], GridArrayComparator), where GridArrayComparator looks for example like:
class GridArrayComparator implements Comparator<Grid[]> {
public int compare(Grid[] grids1, Grid[] grids2) {
if (grids1.length > 0 && grids1.length > 0) {
return grids1[0].compareTo(grids2[0]);
} else if (grids1.length > 0) {
return 1;
} else if (grids2.length > 0) {
return -1;
} else {
return 0;
}
}
}
Then copy 2-d array to 1-d array.
You could create a 2d array instead of 3 separate arrays. Then you could first sort the 2d array to get them in order in relation to each other, then join them.
Grid[][] twoD;
/* ... */
// sort each array separately
for(int i=0; i<twoD.length; i++){
Arrays.sort(twoD[i], /* COMPARATOR */);
}
// sort the arrays based on x coordinate of first element
Arrays.sort(twoD, new Comparator<Grid[]>() {
public int compare(Grid[] a, Grid[] b) {
return Integer.compare(a[0].x, b[0].x);
}
});
/* NOW JOIN THEM */
If there are literally only ever 3 arrays though, you could really just check which is smallest, add that first, etc.
This might be a little bit heavyweight, but works. Assuming you have your array merged which has to be sorted(theArray), you can create a special list view over your array:
private static class BlockBasedListView<T> extends AbstractList<T[]> {
private int blockSize;
private T[] array;
public BlockBasedListView(T[] array, int blockSize) {
this.array = array;
this.blockSize = blockSize;
}
#Override
public T[] get(int index) {
return Arrays.copyOfRange(array, index * blockSize, index * blockSize + blockSize);
}
#Override
public T[] set(int index, T[] element) {
T[] previousElement = get(index);
System.arraycopy(element, 0, array, index * blockSize, blockSize);
return previousElement;
}
#Override
public int size() {
return array.length / blockSize;
}
}
This is a simple list implementation of which one element is a block of elements (with size blockSize) of your original array. Note that this is a view of your array: writes to this list affects the original array.
Then, you create a comparator of a block of Grid:
private static class CompareByFirstElement implements Comparator<Grid[]> {
#Override
public int compare(Grid[] o1, Grid[] o2) {
return o1[0].x - o2[0].x;
}
}
Finally, you can sort theArray as follows:
BlockBasedListView<Grid> blockBasedList = new BlockBasedListView<Grid>(theArray, 5);
Collections.sort(blockBasedList, new CompareByFirstElement());
When you join the sorted arrays you make a new array with size 15. The new array has values which added to it, but has no relation with the subarrays. So, if you apply sort, it would be on the whole array. If you need to sort, you have to use another array variable of size 5, sort that and then write back to main array.
You can use Comparable, maybe this helps..
import java.util.Arrays;
public class Grid implements Comparable<Grid> {
public static void main(String[] args) {
Grid a = new Grid( 2, 15 ); // 3
Grid b = new Grid( 1, 1 ); // 2
Grid c = new Grid( 0, -13 ); // 1
Grid d = new Grid( 4, 0 ); // 4
Grid gridArray[] = new Grid[] { a, b, c, d };
System.out.println( "Printing non sorted:" );
for ( Grid grid : gridArray ) {
System.out.println( grid.getX() + ", " + grid.getY() );
}
System.out.println( "Sorting..." );
Arrays.sort( gridArray );
System.out.println( "Printing sorted:" );
for ( Grid grid : gridArray ) {
System.out.println( grid.getX() + ", " + grid.getY() );
}
}
private int x, y;
public Grid(int x, int y) {
this.setX( x );
this.setY( y );
}
#Override
public int compareTo(Grid grid) {
// ascending order
return this.getX() - grid.getX();
// descending order
// return grid.getX()-this.getX();
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
}
Now Arrays.sort will use natural ordering (Comparable), see:
http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html#sort(java.lang.Object[])
This is the output after executing the given main method:
Printing non sorted:
2, 15
1, 1
0, -13
4, 0
Sorting...
Printing sorted:
0, -13
1, 1
2, 15
4, 0