Sort Array with Two Exceptions in Java - java

I have an array of strings and I need to sort it before I return it. The issue is that two of those values must come first. I tried a few things (including what is below), but I can't seem to figure it out.
What I have below clearly doesn't work because I sort it twice in some cases. I know I can change the array to a list and then use Collections.reverse, but is there a better way that doesn't involve changing structures? I added a simple example below
public static String[] getStrings() {
String[] array = {"d","a","c","e","b"};
boolean first = false;
boolean second = false;
int left = 0;
for (int right = 0; right < array.length; right++) {
if (array[right].equals("e")){
first = true;
array[right] = array[left];
array[left] = "e";
left++;
}
}
if (first) {Arrays.sort(array, left, array.length);}
left = 0;
for (int right = 0; right < array.length; right++) {
if (array[second].equals("c")){
second = true;
array[right] = array[left];
array[left] = "c";
left++;
}
}
if (second) {Arrays.sort(array, left, array.length);}
if (!first && !second) {Arrays.sort(array);}
}
return array;
}
EDIT
Using the array in the example d,a,c,e,b. After the sorting it should be c,e,a,b,d
The two exceptions alphabetically, following the rest of the array alphabetically as well.

You can use the Java 8 Stream API.
final String[] array = {"d","a","c","e","b"};
final Set<String> search = Stream.of("c", "e").collect(toSet());
final String[] result = Stream.concat(
Stream.of(array).filter(search::contains).sorted(),
Stream.of(array).filter(s -> !search.contains(s)).sorted()
).toArray(String[]::new);
The first part selects the "c" and "e" strings and sort them individually, then anything that is not "c" or "e" is selected and sorted individually. Finally, the two streams are concatenated into an array.

How about implementing custom Comparator?
String[] array = {"d","a","c","e","b"};
Arrays.sort(array, new Comparator<String> () {
int compare(String s1, String s2) {
if (firstOne.equals(s1) && firstOne.equals(s2)) {
return 0;
} else if (firstOne.equals(s1) {
return -1;
} else if (firstOne.equals(s2)) {
return 1;
}
if (secondOne.equals(s1) && secondOne.equals(s2)) {
return 0;
} else if (secondOne.equals(s1) {
return -1;
} else if (secondOne.equals(s2)) {
return 1;
}
return s1.compareTo(s2);
});
Refer to
https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html
https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#sort(T[],%20java.util.Comparator)

Take the indices of the elements that you don't want sort and move those elements to the front of the list, then sort the rest of the list.
public static String[] getString(String[] strArray, int... firstElems) {
// Move the elements that are not sorted to the front
int g = 0;
for (int f = 0; f < firstElems.length; f++, g++) {
String elem = strArray[g];
strArray[g] = strArray[firstElems[f]];
strArray[firstElems[f]] = elem;
}
// Sort the rest
Arrays.sort(strArray, g, strArray.length);
return strArray;
}

There is short solution based #ikicha's and Java 8:
final String first = "c", second = "e";
Arrays.sort(array, (i, j) -> {
if (i.equals(first) || (i.equals(second) && !j.equals(first))) {
return -1;
} else {
return i.compareTo(j);
}
});

Why don't you sort it first, then lookup the two values, and shift them upfront?
Worst case would be n*log(n)+2n.

Related

How to remove from an array without using the classes Arrays, Collections, Set, or Map?

test[0] = "one";
test[1] = "two";
test[2] = "one";
test[3] = "three";
I want to remove all the occurrences of "one" but can't use the classes Arrays, Collections, Set, or Map. Thats why I'm stuck, if it wasn't for the restriction I would be able to remove them.
You could have a method like so:
public static String[] removeFromArray(String[] inputArray, String removeString) {
int removeStringOccurences = 0;
for (String currString : inputArray) {
if (currString.equals(removeString)) {
removeStringOccurences++;
}
}
String[] result = new String[inputArray.length - removeStringOccurences];
int index = 0;
for (String currString : inputArray) {
if (!currString.equals(removeString)) {
result[index] = currString;
index++;
}
}
return result;
}
This first checks to see how many times the String we want to remove occurs and then creates a new String[] based on the length of the original String[] minus the times the undesired String occurs.
Running the following:
String[] test = new String[]{"one", "two", "one", "three"};
System.out.println("Before:");
System.out.println(Arrays.toString(test));
test = removeFromArray(test, "one"); //Call our method
System.out.println("\nAfter:");
System.out.println(Arrays.toString(test));
Results in:
Before:
[one, two, one, three]
After:
[two, three]
I think the most appropriate way of solving your issue is to take all of the elements after the element, you want to remove, and shift them one to the front. But this would leave a trail of one unused element.
You could also create a new array without the element to remove.
public void removeFromArrayShift(Object[] arr,int index) {
for(int i = 0;i< arr.length -1;i++){
if(i >= index)
arr[i]=arr[i+1];
}
arr[arr.length-1]=null;
}
public Object[] removeFromArrayNew(Object[] arr, int index) {
Object[] n = new Object[arr.length - 1];
for(int i = 0; i < n.length;i++)
if(i>= index)
n[i] = arr[i+1];
else
n[i] = arr[i];
return n
}
The later could be optimized with System.arrayCopy if you can access that. ;)

How to validate if an Array of strings is sorted in alphabetical order or not using java?

How to validate the String is in alphabetical order or not? It is just to validate that String is in order or not?
Can anybody help me how to validate?
Here is my code::
public class Example3 {
public static void main(String[] args) {
String Month[]={"Jan", "Add", "Siri", "Xenon", "Cat"};
for(int i=0; i<Month.length; i++) {
System.out.println(Month[i]);
}
}
}
You could get the i-th (i >= 1) element and apply compareTo(String other) against the previous one:
boolean ordered = true;
for (int i = 1; i < month.length; i++) {
if (month[i].compareTo(month[i - 1]) < 0) {
ordered = false;
break;
}
}
System.out.println(ordered ? "Ordered" : "Unordered");
Without a loop, just use Collections to compare them since the equals method works fine with this type of objects.
Solution
String[] Month={"Jan", "Add", "Siri", "Xenon", "Cat"};
List<String> copyOf = new ArrayList<>(Arrays.asList(Month));
Collections.sort(copyOf);
if (Arrays.asList(Month).equals(copyOf)){
System.out.println("Sorted");
} else {
System.out.println("Not sorted"); // Not sorted of course but if Month
// was {"Add", "Siri"} it would've been true
}

Searching for a string within an array

Below I am trying to create a method which searches through an array for a certain string and returns the position of it, if not there then -1 should be the number returned. Below I search for a word using the method and it returns -1 even though the word is within the array. Why is this?
String answer = "";
System.out.println("Enter word to search within array");
answer = in.next();
public static int search(String[] theWords, String answer) {
int a = -1;
for(int i = 0; i < theWords.length; i++) {
if (answer.equals(theWords[i])){
a = i;
break;
}
}
return a;
}
I can't see anything wrong with the code, but I would recommend eliminating the local variable that holds the return value:
public static int Search(String[] thewords, String answer) {
for (int i = 0; i < thewords.length; i++) {
if (answer.equals(thewords[i])){
return i;
}
}
return -1;
}
With this simplified logic, there's little or no chance of there being a bug in this code.
I assume this is course work, and you are not allowed to use library methods. If you were allowed, your method could be a single line:
return Arrays.asList(theWords).indexOf(answer);
You can optionally make a copy of the array since sorting might be unwanted for consumers of the method
public static int Search(String[] thewords, String answer) {
if(thewords == null) {
throw new NullPointerException();
}
String[] copy = new String[thewords.length];
System.arraycopy(thewords,0,copy,0,copy.length);
Arrays.sort(thewords);
return Arrays.binarySearch(thewords, answer);
}
Note: It returns -pos and not -1
If you need -1:
public static int Search(String[] thewords, String answer) {
if(thewords == null) {
throw new NullPointerException();
}
String[] copy = new String[thewords.length];
System.arraycopy(thewords,0,copy,0,copy.length);
Arrays.sort(thewords);
int idx = Arrays.binarySearch(thewords, answer);
return idx < 0? -1:idx;
}
Concerning your code: I believe the problem would be related to casing or spacing:
Replace with something like: if (answer.equalsIgnoreCase(theWords[i].trim())){
For large arrays go with binary search.

Sorting String[][] unexpected output

I want to sort my String[][] with respect to second column. I tried this
public static String[][] sorting_minn(String[][] list){
double[] temp = new double[list.length];
String[][] tempf = list;
if(list[1][1]!=null){
for(int i = 0; i<list.length; i++){
if(list[i][2]==null){
break;
} else {
temp[i]=Double.parseDouble(list[i][2]);
}
}
Arrays.sort(temp);
for(int f = 0; f<list.length-1;f++){
for(int m = 0; m<list.length;m++){
if(list[m][2]!=null && Double.parseDouble(list[m][2])==temp[f]){
for(int n = 0; n<4; n++){
tempf[list.length-f-1][n]=list[m][n];
}
m = list.length;
}
}
}
}
return tempf;
}
As an output I get this: . I need suggestion on how to improve this code.
try something like:
Arrays.sort(list, new Comparator<String[]>() {
#Override
public int compare(String[] o1, String[] o2) {
String left = o1[1]!=null ? o1[1] : "";
String right = o2[1]!=null ? o2[1] : "";
return left.compareTo(right);
}
});
this treats nulls as empty strings, and exploits the fact that strings are comparable, although lexicographic. if you want the reverse order just do this instead:
right.compareTo(left)
if you want integer ordering you could parse an Integer out of both sides (Integer.MIN for null) and compare 2 Integers

How to remove specific value from string array in java? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Removing an element from an Array (Java)
How to remove specific String array value for example
String[] str_array = {"item1","item2","item3"};
i want to remove "item2" from str_array pls help me i want output like
String[] str_array = {"item1","item3"};
I would do it as follows:
String[] str_array = {"item1","item2","item3"};
List<String> list = new ArrayList<String>(Arrays.asList(str_array));
list.remove("item2");
str_array = list.toArray(new String[0]);
If you must use arrays, System.arraycopy is the most efficient, scalable solution. However, if you must remove one element from an array several times, you should use an implementation of List rather than an array.
The following utilizes System.arraycopy in order to achieve the desired effect.
public static Object[] remove(Object[] array, Object element) {
if (array.length > 0) {
int index = -1;
for (int i = 0; i < array.length; i++) {
if (array[i].equals(element)) {
index = i;
break;
}
}
if (index >= 0) {
Object[] copy = (Object[]) Array.newInstance(array.getClass()
.getComponentType(), array.length - 1);
if (copy.length > 0) {
System.arraycopy(array, 0, copy, 0, index);
System.arraycopy(array, index + 1, copy, index, copy.length - index);
}
return copy;
}
}
return array;
}
Also, you can increase the method's efficiency if you know that your array consists of only Comparable objects. You can use Arrays.sort to sort them before passing them through the remove method, modified to use Arrays.binarySearch to find index rather than a for loop, raising that portion of the method's efficiency from O(n) to O(nlogn).
Other Option is to copy array to other array accept than remove item.
public static String[] removeItemFromArray(String[] input, String item) {
if (input == null) {
return null;
} else if (input.length <= 0) {
return input;
} else {
String[] output = new String[input.length - 1];
int count = 0;
for (String i : input) {
if (!i.equals(item)) {
output[count++] = i;
}
}
return output;
}
}

Categories