I've been trying everything to sort out this array and seem not working. Every Examobject in the array has String firstName, String lastName, int ID, char examType('M' or 'F'), and int score. The array should be sorted by the first examType -'M' followed immediately by the final 'F' of the same person. Also having trouble with the line if(position[i*2].getID() == r[i+1].getID()). Total 10 objects. I tried to match the exam objects by the ID but still not working. ONLY one loop is allowed!
public static Exam[] collateExams(Exam[] exams)
{
Exam [] r = new Exam[10];
r = exams;
//Exam [] finalExam = new Exam[50];
int[] position = new int[10];
for(int i = 0; i < exams.length; i++)
{
if(r[i].getExamType() == 'M')
{
r[i*2] = new Exam(r[i*2].getFirstName(), r[i*2].getLastName(),
r[i*2].getID(), r[i*2].getExamType(), r[i*2].getScore());
position[i*2] = r[i*2].getID();
if(position[i*2].getID() == r[i+1].getID())
r[i+1] = new Exam(r[i+1].getFirstName(), r[i+1].getLastName(),
r[i+1].getID(), r[i+1].getExamType(), r[i+1].getScore());
}
/*if((r[i].getExamType() == 'F') && (position[i] == r[i].getID()))
{
}*/
}
return r;
}
}
something like this:
class ExamComparator implements Comparator {
public int compare(Exam e1, Exam e2) {
return e1.getExamType() == e2.getExamType() ? 0 : (e1.getExamType() == 'F' ? 1 : -1);
}
}
Arrays.sort(exams, new ExamComparator());
Use Arrays.sort with your custom Comparator which will use values you want.
As #djechlin explained you can use ,Arrays.sort with your own custom comparator like mentioned in below example , You can use List or Array whatever you want its upto you ,
List<String> list=Arrays.asList("XYZ","ABC","DEF");
String [] stringArray=new String[]{"XYZ","ABC","DEF"};
Arrays.sort(stringArray,new Comparator(){
public int compare(Object one,Object two){
String first=(String)one;
String second=(String)two;
return first.compareTo(second);
}
});
for(String s:stringArray){
System.out.print(s+"\t");
}
Collections.sort(list,new Comparator(){
public int compare(Object one,Object two){
String first=(String)one;
String second=(String)two;
return first.compareTo(second);
}
});
System.out.println(list);
Output
ABC DEF XYZ // for Arrays.sort
[ABC DEF XYZ]// for Collections.sort
Now Coming to your actuall problem
The array should be sorted by the first examType -'M' followed
immediately by the final 'F' of the same person
You have to create your own custom comparator which does the sorting based on examType
Related
ArrayList<String> heights = new ArrayList<String>();
Comparator<String> setTableNumber = new Comparator<String>(){
#Override
public int compare(String o1, String o2){{
return (o1).compareTo(o2);}}};
Collections.sort(players, setTableNumber);
Suppose heights consists Strings that are like this ["5'11"", "6'11"","4'2""]
And I want it to sort from highest to lowest like ["6'11"","5'11"","4'2""]
I'm thinking about using .split('), converting the strings to integers and then multiplying the feet by 12 and then adding that to the second string (after I trim off the ") and comparing two values as inches. But is there a better way to do it?
Thanks in advance.
Personally, I'd convert the String values to int (inches) up-front, this gives you the opportunity to deal with possible errors during conversation.
ArrayList<String> heights = new ArrayList<String>();
heights.add("5'11");
heights.add("6'11");
heights.add("5'2");
heights.add("4'2");
Comparator<String> setTableNumber = new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
Integer lhs = convertToInches(o1);
Integer rhs = convertToInches(o2);
if (lhs == null) {
return 1;
} else if (rhs == null) {
return -1;
}
return lhs.compareTo(rhs);
}
protected Integer convertToInches(String value) {
String parts[] = value.split("'");
if (parts.length != 2) {
return null;
}
return (Integer.parseInt(parts[0]) * 12) + Integer.parseInt(parts[1]);
}
};
Collections.sort(heights, setTableNumber);
System.out.println(heights);
which prints
[4'2, 5'2, 5'11, 6'11]
This workflow will place "bad" values to the end of the list, for example...
ArrayList<String> heights = new ArrayList<String>();
heights.add("Worse");
heights.add("5'11");
heights.add("6'11");
heights.add("5'2");
heights.add("Bad");
heights.add("4'2");
will generate
[4'2, 5'2, 5'11, 6'11, Worse, Bad]
But personally, I'd deal with this before trying to sort the list (by converting the values to int). You can then do some additional formatting to the int values when you want to print it
It is inefficient to do a lot of things each time you compare.
Try this.
public static void main(String[] args) {
List<String> heights = List.of("5'11\"", "6'11\"","4'2\"");
List<String> sorted = heights.stream()
.map(s -> new Object() {
String feetInch = s;
int inch;
{
String[] f = feetInch.replaceFirst("\"", "").split("'");
inch = Integer.parseInt(f[0]) * 12 + Integer.parseInt(f[1]);
}
})
.sorted(Collections.reverseOrder(Comparator.comparing(obj -> obj.inch)))
.map(obj -> obj.feetInch)
.toList();
System.out.println(sorted);
}
output:
[6'11", 5'11", 4'2"]
So I had a delimited file that I read into an array.
array[0] is the boxID (double)
and
array[1] is the movieID (double)
I have no clue how I'd be able to sort my array by these two doubles. Any comments? I've tried looking at other questions on this website but I just got confused by them. I'm currently in my first programming class.
Movies[] newMasterMovies = new Movies[200];
int newMasterCount = 0;
int masterCount = 0;
int updateCount = 0;
while (updateCount < updateTotalCounter || masterCount < masterTotalCounter) {
String updateCompare = updateMovies[updateCount].getBoxID() + updateMovies[updateCount].getMovieID();
String masterCompare = masterMovies[masterCount].getBoxID() + masterMovies[masterCount].getMovieID();
int compare = updateCompare.compareTo(masterCompare);
if (compare > 0) {
newMasterMovies[newMasterCount] = masterMovies[masterCount];
masterCount++;
newMasterCount++;
}
if (updateMovies[updateCount].getActionCode() == "A") {
newMasterMovies[newMasterCount] = updateMovies[updateCount];
updateCount++;
newMasterCount++;
}
if (updateMovies[updateCount].getActionCode() == "D") {
updateCount++;
masterCount++;
}
if (updateMovies[updateCount].getActionCode() == "C") {
newMasterMovies[newMasterCount] = updateMovies[updateCount];
updateCount++;
newMasterCount++;
masterCount++;
}
}
That is what my array looks like that I am trying to sort. I tried to do a selection sort but got confused since I want to sort by two properties, not just one.
This guy here does a wonders
Arrays.sort(iArr);
Here is what it can do:
Here is an example code
public class ArrayDemo {
public static void main(String[] args) {
// initializing unsorted int array
int iArr[] = {2, 1, 9, 6, 4};
// let us print all the elements available in list
for (int number : iArr) {
System.out.println("Number = " + number);
}
// sorting array
Arrays.sort(iArr);
// let us print all the elements available in list
System.out.println("The sorted int array is:");
for (int number : iArr) {
System.out.println("Number = " + number);
}
}
}
And the results should be like this
Number = 2
Number = 1
Number = 9
Number = 6
Number = 4
The sorted int array is:
Number = 1
Number = 2
Number = 4
Number = 6
Number = 9
Hopes this helps some
To simply sort your Movies[] you can use Arrays.sort and use a custom Comparator. Like this:
Arrays.sort(masterMovies, new Comparator<Movies>() {
#Override
public int compare(Movies o1, Movies o2) {
// compare boxID
// compare movieID
return 0; // return result
}
});
Arrays.sort use merge sort or binary insertion sort which are both more stable and faster than selection sort.
If you insist to do your selection sort, try to edit yor class Movies to implement Comparable interface, like this: class Movies implements Comparable<Movies>. And implement compareTo method like this:
#Override
public int compareTo(Movies o) {
// compare boxID
// compare movieID
return 0; // return result
}
And change your old compare code int compare = updateCompare.compareTo(masterCompare); to int compare=updateMovies[updateCount].compareTo(masterMovies[masterCount]);, then go on.
I have an array that looks like:
array[] = {1c, 13d, 11d, 10d, 1h, 13h, 5s, 2s, 12d}
I want to sort the array based on the number present in the array So the end result would be:
{1c, 1h, 2s, 5s, 10d, 11d, 12d, 13d, 13h}
Is there a way to do it?
The best way to do this is by implementing the Comparator interface. When you decide how you plan to compare the strings, you can use the utility methods in Arrays class. Here is a complete working example.
import java.util.Arrays;
import java.util.Comparator;
public class Foo {
public static void main(String[] args) {
String[] myArray = {"1c", "13d", "11d", "10d", "1h", "13h", "5s", "2s", "12d"};
System.out.println(Arrays.toString(myArray));
Arrays.sort(myArray, new Comparator<String>() {
#Override
public int compare(String one, String two) {
int oneNum = Integer.parseInt(one.substring(0, one.length() - 1));
int twoNum = Integer.parseInt(two.substring(0, two.length() - 1));
char oneChar = one.charAt(one.length() - 1);
char twoChar = two.charAt(two.length() - 1);
if (oneNum < twoNum) {
return -1;
} else if (oneNum == twoNum) {
if (oneChar < twoChar) {
return -1;
} else if (oneChar == twoChar){
return 0;
} else {
return 1;
}
} else {
return 1;
}
}
}
);
System.out.println(Arrays.toString(myArray));
}
}
Think about how you'd do this with just paper and pencil (no computer). Chances are you would:
Go through each element of the array, and convert it to just an integer (i.e. remove the non-numerical characters)
Sort the resulting integer-only array or list. Hint: Collections.sort() is your friend :)
i need to sort names list in to alphabetical order, for this i use the interfase comperator for sorting the names
#Override
public int compareTo(ContactModel another) {
// TODO Auto-generated method stub
return getname().compareTo(another.getname());
}
Suppose this is my array of name
123vinish
23Sathya
24mahesh
Ranjith
Vipin
Bibin
Shine
Thomas
i need to sort this in a sequence where names with numbers must come last
Bibin
Ranjith
Shine
Thomas
Vipin
123Vinish
23Sathya
24mahesh
How can we implement this
String.compareTo(String) sort the Strings by the ascii value of the characters. You need to change the comparator. Example with a custom comparator:
List<String> al = new ArrayList<String>();
al.add("123vinish");
al.add("23Sathya");
al.add("24mahesh");
al.add("Ranjith");
al.add("Vipin");
al.add("Bibin");
al.add("Shine");
al.add("Thomas");
Comparator<String> nameComparator = new Comparator<String>()
{
#Override
public int compare(String value1, String value2)
{
if(Character.isDigit(value1.charAt(0))&&!Character.isDigit(value2.charAt(0)))
return 1;
if(Character.isDigit(value2.charAt(0))&&!Character.isDigit(value1.charAt(0)))
return -1;
return value1.compareTo(value2);
}
};
Collections.sort(al, nameComparator);
System.out.println(al);
Output: [Bibin, Ranjith, Shine, Thomas, Vipin, 123vinish, 23Sathya, 24mahesh]
And if you want to override the compareTo method in the class where you implemented the Comparable<> interface, it have to look like this:
#Override
public int compareTo(ContactModel anotherValue)
{
if(Character.isDigit(this.getname().charAt(0))&&!Character.isDigit(anotherValue.getname().charAt(0)))
return 1;
if(Character.isDigit(anotherValue.getname().charAt(0))&&!Character.isDigit(this.getname().charAt(0)))
return -1;
return this.getname().compareTo(anotherValue.getname());
}
EDIT:
If you want that a String like 2a appear before something like 23 then you only have to loop over every character in the String. Then the custom comparator have to look like this:
Comparator<String> nameComparator = new Comparator<String>()
{
#Override
public int compare(String value1, String value2)
{
for(int i = 0; i < Math.min(value1.length(), value2.length()); i++)
{
//value1 is digit and value2 is not
if(Character.isDigit(value1.charAt(i)) && !Character.isDigit(value2.charAt(i)))
return 1;
//value2 is digit and value1 is not
else if(Character.isDigit(value2.charAt(i)) && !Character.isDigit(value1.charAt(i)))
return -1;
//both are digits with different size
else if(Character.isDigit(value1.charAt(i)) && Character.isDigit(value2.charAt(i)) && Integer.valueOf(value1.charAt(i))!=Integer.valueOf(value2.charAt(i)))
return value1.compareTo(value2);
//both are no digits
else if(!Character.isDigit(value1.charAt(i)) && !Character.isDigit(value2.charAt(i)))
return value1.compareTo(value2);
//loop again if they are both digits with the same value
}
return value1.compareTo(value2);
}
};
EDIT 2:
I have creat another solution for your problem. I've copied the implementation of the compareTo method in String class and modified the ascii values of numbers while the comparing. This example can be used in your ContactModel class.
#Override
public int compareTo(ContactModel anotherValue) {
int len1 = this.getname().length();
int len2 = anotherValue.getname().length();
int lim = Math.min(len1, len2);
char v1[] = this.getname().toCharArray();
char v2[] = anotherValue.getname().toCharArray();
int k = 0;
while (k < lim) {
//Do the trick here! If char is a digit, add 75.
char c1 = Character.isDigit(v1[k]) ? ((char)(v1[k]+75)) : v1[k];
char c2 = Character.isDigit(v2[k]) ? ((char)(v2[k]+75)) : v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
What about this implementation almost similar to your 2nd suggestion
#Override
public int compareTo(ContactModel another) {
// TODO Auto-generated method stub
boolean lhsStartsWithDigit = Character.isDigit(getStartLetter().charAt(0));
boolean rhsStartsWithDigit= Character.isDigit(another.getStartLetter().charAt(0));
if((lhsStartsWithDigit && rhsStartsWithDigit) || (!lhsStartsWithDigit && ! rhsStartsWithDigit))
return getStartLetter().compareToIgnoreCase(another.getStartLetter());
else if(lhsStartsWithDigit)
return 1;
else
return -1;
}
Can i follow this??
Is there an easy way of finding the MAX number from the list where number is stored in x.y.z format? e.g. To manage some system versions.
I have tried Collection.max(list) and that does not work.
Sample Code:
public static void main(String args[])
{
List<String> list = new ArrayList<String>();
list.add("1.0.0");
list.add("1.1.0");
list.add("1.9.0");
list.add("1.10.0");
System.out.println(Collections.max(list));
}
Expected: 1.10.0
Result: 1.9
Thanks for your time.
Try to use this one :
Collections.max(myList, new Comparator<String>() {
#Override
public int compare(String lhs, String rhs) {
String[] first = lhs.split("\\.");
String[] second = rhs.split("\\.");
for (int i = 0; i < first.length; i++) {
if(Integer.valueOf(first[i]) > Integer.valueOf(second[i])) {
return 1;
}
if(Integer.valueOf(first[i]) < Integer.valueOf(second[i])) {
return -1;
}
}
return 0;
}
});
Well for one thing, you need to ensure that Java knows they are numbers - at the moment they're just Strings, and strings sort lexigraphically (i.e. in "alphabetical order").
My approach to this would be to create a small class that implements Comparable, which will then work automatically with sorting and comparison logic. Something like this perhaps:
public class VersionNumber implements Comparable<VersionNumber> {
public final int major;
public final int minor;
public final int patch;
// Constructor etc. elided
public int compareTo(VersionNumber other) {
if (other.major != major) return major - other.major;
if (other.minor != minor) return minor - other.minor;
return patch - other.patch;
}
}
Parsing the string to create instances of this class is left as an exercise to the reader!
You may have to write a custom Comparator for comparing version number strings:
public class VersionComparator extends Comparator<String> {
#Override
public int compare(String o1, String o2) {
// Get major/minor/revison numbers by splitting strings at dots
String[] p1 = o1.split("\\.");
String[] p2 = o2.split("\\.");
// Compare major versions then minor then revision until a difference found
for(int i = 0; i < (p1.length < p2.length) ? p1.length : p2.length; i++) {
int result = Integer.valueOf(p1[i]).compareTo(Integer.valueOf(p2[i]));
if(result != 0) return result;
}
// Return zero if they're identical
return 0;
}
}
The you can use this comparator with the Collections.max function:
Collections.max(list, new VarsionComparator());
You can use version of max with the specified comparator:
System.out.println(Collections.max(list, new Comparator<String>() {
public int compare(String s1, String s2)
{
StringTokenizer st1 = new StringTokenizer(s1,".");
StringTokenizer st2 = new StringTokenizer(s2,".");
int res = 0;
String t1, t2;
while(st1.hasMoreTokens() && st2.hasMoreTokens())
{
t1 = st1.nextToken();
t2 = st2.nextToken();
res = Integer.valueOf(t1).compareTo(Integer.valueOf(t2));
}
if(res == 0)
{
res = st1.hasMoreTokens() ? 1 : (st2.hasMoreTokens() ? -1 : 0);
}
return res;
}
public boolean equals(Object obj) { return false; }
}));
This will give you 1.9 because it will not consider second number to be 10, it will treat it as 1 first and then 9
Edit
If you want to do it manually, then
Split your number on basis of "."
Check manually which number is greater.