I am working on 2D array and I need to organize my array.
Explanation, my array is an Array String and it's containing in the header some double value, and I want to sort the array in function of the header.
The first thing I thought was to get the header and sort the header, get all the columns of the array in another array and comparate the value of the header ordered to each column index[0] and push to another array.
However, I thought there is a way to do it easily, but I don't know if there is, I saw the possibility to sort directly in the array and organize in function of this but I have no idea how to it.
Just in case :
Original array
String[][]myArray = {{3,Toto,30},{2,Tata,29},{1,Titi,13}};
Array expected
String[][]newArray = {{1,Titi,13},{2,Tata,29},{3,Toto,30}};
Open to proposal!
Thanks.
Edit : The header could be Double value.
If I understood you correctly, seems like this:
Arrays.stream(myArray)
.sorted(Comparator.comparingDouble(x -> Double.valueOf(x[0])))
.toArray(String[][]::new);
Of course you can do that in place too, via Arrays::sort and that Comparator
Previous answer just returned the original array when I tried it. Here's what worked for me:
String[][] myArray = {{"3","Toto","30"},{"2","Tata","29"},{"1","Titi","13"}};
Arrays.sort(myArray, new Comparator<String[]>() {
public int compare(String[] lhs, String[] rhs) {
try {
double lhs_value = Double.parseDouble(lhs[0]);
double rhs_value = Double.parseDouble(rhs[0]);
if (lhs_value < rhs_value) return -1;
if (lhs_value > rhs_value) return 1;
return 0; //else the two are equal
} catch (NumberFormatException e) {
//handle exception
return 0;
}
}
});
My output:
1 Titi 13
2 Tata 29
3 Toto 30
Here Arrays.sort (see Javadoc) takes in two parameters: an array you're sorting (myArray), and a Comparator (see Javadoc), which is an interface that allows comparison between two arbitrary types. Since {"3", "Toto", "30"} isn't a type you created, and is just a String[], we're going to make a Comparator<String[]> inline.
Comparators implement a function "compare" which takes in two elements, and returns -1, 0, or 1 to determine the ordering of the elements. Essentially "compare" gets called multiple times in the sorting process to precisely determine sorted order. Here's some pseudocode:
public int compare(Object a, Object b)
if (a comes "before" b) return -1
if (a is "equal" to b) return 0
if (a comes "after" b) return 1
If that isn't clear, you can learn more about the Comparator interface here:
https://www.geeksforgeeks.org/comparator-interface-java/
I know I used "before" and "after" earlier, which are a little fuzzy and non-rigorous. If you're more mathematically inclined, here's a good discussion of the Comparator interface:
https://math.stackexchange.com/questions/1400655/java-comparator-documentation-confused-about-the-terminology-total-order
Related
I was using Arrays.sort() function to sort 2d array (int[][] array). Since I want to sort it base on the first element. For example, {{2,3},{1,4}} base on 1st element the array will be {{1,4},{2,3}}. So I override the compare function.
Arrays.sort(arr, new Comparator<int[]>() {
#Override
public int compare(int[] o1, int[] o2){
if(o1[0] < o2[0]){
return -1;
} else if (o1[0] > o2[0]) {
return 1;
} else {
return 0;
}
}
})
I know this sort work. But I don't understand how this compare work.
I was thinking the
new Comparator<int[]>
should be
new Comparator<int[][]>
since this is 2d array. and inside of compare function should be compare
o1[0][0] and o2[0][0]
Can anyone help me understand it?
Also this is using Arrays.sort, can I use Collections.sort? what is different between it?
Thanks
Remember that a "2D array" doesn't actually exist in Java, so what you're really dealing with is "an array of int[]" (there's nothing inherently preventing each of those int[] from being a different length).
So: when you sort, you're comparing individual elements of that "array of int[]" with each other, and because each element is an int[], your Comparator is for int[], too.
You are passing the array in the sort method and giving it a comparator. Arrays.sort will use iterator to pass into compare method. So compare method is checking element at arr[0].compare(arr[1]) sorts these 2 and goes to next iterator. same concept applies using 2d array. You are just passing 2 arrays and telling compare who should be placed where.
the problem I encountered is not somewhat special, however, being relatively new to programming I find myself in a situation where I need some help from more advanced coders. The problem I have is sorting a list of objects, which have a varying size, based on their certain element.
I have a set of data in picture below.
As you can see, the data consists 8 rows with different amount of string elements. My goal is to have these row objects sorted by columns.
What I mean - first, the rows are sorted by the first element of each row. So if the initial row arrangement according to the first elements of each row is [-2.2, 2.2, 2.2, -22, -22, -22, -1.1, qqqq], sorted arrangement would look like [-22, -22, -22, -2.2, -1.1, 2.2, 2.2, qqqq]. Then, since there are some rows with the same elements (0,1,2 row) and (5,6 row), these rows would be sorted by the second element - in this case, these second elements are 1234234, 11, -3 for rows with first element of -22 and 12345q, 12345q for rows with first element of 2.2.
After this, the two rows consisting 12345q as their second element would be sorted by third element, which for both are 69, and 4th elements would be reached (-afg and -asdf) which then would be sorted. The final result should look like on picture below
Now, I've done an extensive search on stackoverflow and the closest I would get to my case was Java sort based on two columns. I understand the steps I need to take in order to solve the probem (create a list, create a comparator etc.) but only in theory.
I have a List of Strings[] named rowObject, which contains all the rows with their respective string elements, whose amount, as I mentioned before, vary from row to row. I also have a comparator which does the sorting job exactly as it is needed, however, it is written in the compare method:
public class ComparatorClass {
public List compare(List<String> listOfValues) {
Comparator<String> c = new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
boolean b1 = s1.matches(".*[^0-9.\\-].*");
boolean b2 = s2.matches(".*[^0-9.\\-].*");
// if both are gonna find doubles
if (!b1 && !b2) {
Double d1 = Double.parseDouble(s1);
Double d2 = Double.parseDouble(s2);
return d1.compareTo(d2);
}
// if both are text, then compare as strings
else if (b1 && b2) {
return s1.compareTo(s2);
}
// otherwise return one or the other, depending on which is text/number
else return b2 ? -1 : 1;
}
};
Collections.sort(listOfValues, c);
return listOfValues;
}
Hence, I have a List of objects, which I need to sort according to their values, I have a Comparator, but I do not know how to put them all together to sort everything smoothly and in a gentle manner. I also do not know how to access the certain value of these objects in a good way, like String firstvalue = rowObject.get(i)[0] is pretty lame. Any help, advices, examples on how to glue everything together and produce the needed output is appreciated, thank you in advance.
It kind of depends on the data structure you have chosen. For example using arrays might be a bit harder to implement using the Comparator pattern. But if you have list of lists you can do it like that:
public class ComparatorClass implements Comparator<List<String>>{
private int compare(String s1, String s2) {
boolean b1 = s1.matches(".*[^0-9.\\-].*");
boolean b2 = s2.matches(".*[^0-9.\\-].*");
// if both are gonna find doubles
if (!b1 && !b2) {
Double d1 = Double.parseDouble(s1);
Double d2 = Double.parseDouble(s2);
return d1.compareTo(d2);
}
// if both are text, then compare as strings
else if (b1 && b2) {
return s1.compareTo(s2);
}
// otherwise return one or the other, depending on which is text/number
else return b2 ? -1 : 1;
}
#Override
public int compare(List<String> o1, List<String> o2) {
for(int i=0;i<Math.min(o1.size(), o2.size()); i++) {
int comparedAtThisLevel=compare(o1.get(i),o2.get(i));
if(comparedAtThisLevel!=0)
return comparedAtThisLevel;
}
return Integer.compare(o1.size(),o2.size());
}
}
This is a comparator for list of strings (and not just for two strings). I used your method to compare the two strings on the same level but then I iterate through the list of values and compare 1st with 1st, 2nd with 2nd, 3rd with 3rd etc. If all values match (or one of the lists ends) we compare the sizes and take the longer one
Then you can test it with that:
public static void main(String[] args) {
System.out.println(new Date()+": Let's start our StackOverflow helper project!");
List<List<String>> listOfLists=new ArrayList<>();
listOfLists.add(Arrays.asList("-22","123456","4234","5435345"));
listOfLists.add(Arrays.asList("-22","-3","-4"));
listOfLists.add(Arrays.asList("-22","11","Pillow"));
Collections.sort(listOfLists, new ComparatorClass());
}
Is there a way i could return in an array the common elements of 2 or more arrays? I know having some of the methods under lists could do it but is there a way to do it by only using arrays? I made my own get and length btw since i am creating a an array called OrderedIntList.
Example would be:
1,3,5
1,6,7,9,3
1,3,10,11
Result: 1,3
I tried this and it outputs the common elements between two arrays and not all.
I know there's something wrong but i do not how to make it work like it suppose to work :(
//returns the common elements of inputted arrays
public static OrderedIntList common(OrderedIntList ... lists){
int[] list = new int[10];
for(int x = 1; x <= lists.length -1; x++){
for(int q = 0; q < lists[0].length()-1; q++) {
for(int z = 0; z < lists[x].length(); z++) {
if (lists[0].get(q)==lists[x].get(z)){
list[q] = lists[0].get(q);
}
}
}
}
OrderedIntList newlist = new OrderedIntList(list);
return newlist;
}
This can be an easy algorithm to solve it...
1) Instantiate an instance variable of type array called
"commonElements" pointing to the elements of the first Array. At the
beginning these are your common elements.
2) Create a method call getCommonElements(int[] commonElements,
int[] newList). This method manipulates the commonElements array to leave
it with only the common elements between the two. (p.s Use a temporary
array to achieve this if you find it easier)
3) Iterate over all the arrays present in "lists" starting from the
second array.
4) call the method at point 2 for each array .
All the difficult part for you it's to implement a method that given 2 arrays finds the common elements!
You can use
org.apache.commons.collections.CollectionUtils.intersection(java.util.Collection a, java.util.Collection b)
to get the intersection of two lists (elements presents in both lists)
And to pass your array as a Collection: java.util.Arrays.asList(Object[] a);
But working on arrays is tedious, at best. You should consider why you don't want to use a Collection...
As a partial answer, you're probably doing too much work by fully reimplementing an OrderedIntList the way you're doing, since ArrayList and friends already come with sorting baked in via the Collections class.
import java.util.Collections;
public class OrderedIntList extends ArrayList<Integer> {
#override // to effect sorted inserts
public void add(Integer i) {
this.add(i);
Collections.sort(this);
// done.
}
}
Wanting to do this for pure arrays is a nice exercise, but then you'll be better of implementing sorting properly with a quick sort (you can't websearch for a java implementation of that without getting a million results) or an insert sort (equally websearchable), and follow the same recipe.
any time you push a number into the array:
guess where the number goes (although that's optional),
insert the number,
resort your array if you know your guess wasn't perfect.
This is probably a simple question, but I have two arrays of approx 1000 elements each, they are called posXArray and posYArray. I want to sort posYArray numerically (lowest number first) but I want the elements of posXArray to have the same operation applied to them...
For example, if element [56] of posYArray is the smallest one , I want element [56] of posXArray to also be moved to [0].
How is this implemented in Java in an easy/good way?
Thank you very much for you help!
Since the arrays seem to contain X and Y coordinates, perhaps a better choice is to create a coordinate class containing both values, implement Comparable and just have a single array to sort using the built-in algorithms?
Create a class like:
public class XYPos implements Comparable<XYPos> {
int x;
int y;
#Override
public int compareTo(XYPos o) {
int res = this.y - o.y;
if(res == 0) {
res = this.x - o.x;
}
return res;
}
}
Then:
convert your 2 arrays into one array of XYPos
sort it
update your 2 original arrays with the values in the sorted array
Create an Integer[] idx of the same length and fill it with the numbers 0 to 999 (or whatever), then sort this array using a comparator that does
public int compare(Integer a, Integer b) {
return posYArray[a] - posYArray[b];
}
This will give you an array of indexes into the other arrays, i.e. the smallest Y value will be posYArray[idx[0]] and its corresponding X will be posXArray[idx[0]], etc. If you don't want to maintain the indirection you could re-order the original arrays by the idx values.
If you're doing this sort of thing regularly you may wish to look at fastutil which provides Collection and Comparator types that operate directly on primitive types such as int, avoiding the need to box and unbox Integers.
You could implement any sorting algorithm of your choice, do the comparation check on the first (posXArray) only, and then swap position of elements in both arrays at the same time.
I have 2 arrays of data in Java. Based on the order of first array I have to sort the next array.
E.g -
String[] Array1 = {"EUROPE","MIDDLEEAST","OTHERs","AUSTRALIA"};
String[] Array2 = {"MIDDLEEAST","EUROPE","AUSTRALIA","OTHERs","ASIA","EUROPE"};
My output should look like:
{"EUROPE","EUROPE","MIDDLEEAST","OTHERs","AUSTRALIA","ASIA"}
What is the best way to do it?
To sort you need to define a sorting order so given element A and B, you can determine easily if A should go before or after B in the sorted list.
This concept is formalized with the concept of a Comparator in Java.
In this case the sorting order is defined by the order of the elements in a list. The simplest approach is given A and B to find each of them in the original list, note the index found, and compare the indexes to find out which one goes first.
Depending on the size of your data this might be too slow. You can then create a HashMap<String,Long> which holds the index of a given string in Array1. Here it would hold "DEF"->0, "ABC"->1, "XYZ"->2.
May be this:
1) Sort both of them.
2) Create blank result table
3) Take first elem from sorted Array2 and put it to result table with the original index of the first elem on sorted Array1
3) Repeat the step 3 on the second element and so on.
The computational complexity would be like sorting method used: O(nlogn) for quicksort
You can definitely do this in O(n log n). But the best approach depends on what is more important: quick, clean code or not allocating extra memory.
If you don't care about using extra memory, you can allocate a separate array, where each element is a pair:
public class Pair implements Comparable {
...
}
Then you would sort the array of pairs using Arrays.sort(Object[]).
If you don't want to allocate quite so much space, you can use an auxiliary array that contains the indexes in Integer form:
final String[] array1 = ...;
final String[] array2 = ...;
assert array1.length == array2.length;
Comparator<Integer> c = new Comparator<Integer> {
int compare(Integer a, Integer b) {
return array1[a].compareTo(array1[b]);
}
};
Integer[] aux = new Integer[array1.length];
for (int i = 0; i < aux.length; ++i) { aux[i] = i; }
Arrays.sort(aux, c);
String[] result = new String[array1.length];
for (int i = 0; i < aux.length; ++i) {
result[i] = array2[aux[i]];
}
If you are trying to do the entire thing in-place and not allocate additional memory, then you will need to implement one of the n-log-n sort algorithms yourself...
There are (at least) two ways to sort one array and reorder a second array so corresponding elements still match. Both require constructing a third array and writing a custom comparison function.
Method 1
Define a custom object that contains one element of each array. (In your case, it might be a two-element String array.) Write a comparator (or implement Comparable) for the custom object that simply compares the elements from the first array. Build an array of the custom objects from the two input arrays, sort the third array, and then extract the results.
This is the method most commonly recommended for this problem.
Method 2
Construct an array of Integer indexes initialized to 0, 1, 2, ..., n-1 (where n == Array1.length). Sort the index array using a comparator that compares indexes by comparing the Array1 elements that they index.
The second method will be faster and will not require as much object construction.
Two other ideas:
Could these values be an enum rather than a set of strings? The natural order of an enum is the order of declaration, so Arrays.sort() would just work.
Helper code exists in Guava's Ordering.explicitOrder(List):
String[] explicitOrder = {"EUROPE", "MIDDLEEAST", "OTHERs", "AUSTRALIA"};
String[] toSort = ...
Comparator<String> comparator = Ordering.explicit(Arrays.asList(explicitOrder));
String[] sorted = Arrays.sort(toSort, comparator);