I was given a task to sort multidimensional array into ascending order without using the pre-made functions in the Array class (such as .sort).
I've tried asking some of my friends for ideas... Many of them turns the array into a single-dimensional array, sort it the way you would sort a single-dimensional array and then turns it back into a multidimensional array.
I'm just curious to know if there'd be any other ways to do this without having to go through such trouble.
I've found a solution... Thanks all
public static void sortAscending(int array[][]) {
int temp = 0;
for(int i = 0; i < array.length; i++) {
for(int j = 0; j < array[i].length; j++) {
for(int k = 0; k < array.length; k++) {
for(int l = 0; l < array[k].length; l++) {
if(array[i][j] < array[k][l]) {
temp = array[i][j];
array[i][j] = array[k][l];
array[k][l] = temp;
}
}
}
}
}
}
here is a full exemple you can tri
import java.util.Arrays;
import java.util.Comparator;
public class PartNumberQuantityDetailer {
// initialize a two dimensional array
static Integer[][] itemIdAndQty = new Integer[5][2];
public static void main(String[] args) {
// initialize array values
itemIdAndQty[0][0] = 1234;
itemIdAndQty[0][1] = 46;
itemIdAndQty[1][0] = 5443;
itemIdAndQty[1][1] = 564;
itemIdAndQty[2][0] = 362;
itemIdAndQty[2][1] = 24;
itemIdAndQty[3][0] = 6742;
itemIdAndQty[3][1] = 825;
itemIdAndQty[4][0] = 347;
itemIdAndQty[4][1] = 549;
System.out.println("Before sorting");
// show the contents of array
displayArray();
// sort the array on item id(first column)
Arrays.sort(itemIdAndQty, new Comparator<Integer[]>() {
#Override
//arguments to this method represent the arrays to be sorted
public int compare(Integer[] o1, Integer[] o2) {
//get the item ids which are at index 0 of the array
Integer itemIdOne = o1[0];
Integer itemIdTwo = o2[0];
// sort on item id
return itemIdOne.compareTo(itemIdTwo);
}
});
// display array after sort
System.out.println("After sorting on item id in ascending order");
displayArray();
// sort array on quantity(second column)
Arrays.sort(itemIdAndQty, new Comparator<Integer[]>() {
#Override
public int compare(Integer[] o1, Integer[] o2) {
Integer quantityOne = o1[1];
Integer quantityTwo = o2[1];
// reverse sort on quantity
return quantityOne.compareTo(quantityTwo);
}
});
// display array after sort
System.out.println("After sorting on quantity in ascending order");
displayArray();
}
private static void displayArray() {
System.out.println("-------------------------------------");
System.out.println("Item id\t\tQuantity");
for (int i = 0; i < itemIdAndQty.length; i++) {
Integer[] itemRecord = itemIdAndQty[i];
System.out.println(itemRecord[0] + "\t\t" + itemRecord[1]);
}
System.out.println("-------------------------------------");
}
}]
sort multidimensional array into ascending order:
You can sort multi-d array row-wise or column -wise.
If you don't want to flatten the array that is convert it into 1-d then that mean you have to go through each row or column depending on your choice and apply quick-sort(better performance for small data set if pivot is chosen optimally) or merge-sort.
So you can do both in (considering avg. case) O(nlogn) and say there are n rown or n columns the time complexity will be O(n^2(logn)).
Now above the assumption is that you want to sort either row-wise or column-wise.
If you want to achieve the both(row and column) then it's better if you convert the array to 1-d and then apply sort and then convert it back. Otherwise following above approach the time complexity can go O(n^2(logn)) but in the other case it will be O((n+m)log(n+m)) where n amd m are no. of rows and columns in array plus the O(n+m) space complexity.
In my opinion having a bit of space complexity so that you can bring down the run-time is preferable.
Related
I have to create a method that will remove at certain value from an array and create a new array without that certain value. For example, if my array is (0,2,3,5,3) and I want to remove 3, the new array should be (0,2,5). For some reason, it only works for the first two digits.
import java.util.Scanner;
public class removeDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
//array of numbers
int array[] = new int[] {0,1,2,3,4,5};
//invokes method and prints result
//System.out.println(remove(3,array));
remove(3,array);
}
//method remove that removes selected number from array
public static int[] remove(int v, int[] in) {
//count variable counts how many non-target numbers
int count = 0;
//for loop that checks if value at certain index is not equal to "v", the target number for removal
for(int k = 0; k < in.length; k++) {
//checks if certain number at certain index of array is not equal to v, or in this case, 3
if(in[k] != v) {
//counter
count++;
}
}
//new array that will stores values except "v"
int copy[] = new int[count];
//prints the length
System.out.println("array length: " + copy.length);
//for loop that checks if number not 3
for(int a = 1; a < in.length;) {
// sets number at certain index of main array into new array
if(in[a] != 3){
copy[a] = in[a];
a++;
System.out.println(copy[0]);
System.out.println(copy[1]);
System.out.println(copy[2]);
System.out.println(copy[3]);
}
else if(in[a] == 3) {
copy[a] = in[a+1];
}
}
//returns new array
return copy;
}
}
As said before, I need the new array to exclude the targeted number for removal.
You need two index variables for making the copy: one runs through the input array (a, as in the original code), and the other tracks your position in the output array (b, new variable). They can not be calculated from each other (they are the same at the beginning, but b can be significantly less than a at the end)
int b = 0;
for(int a = 0; a < in.length; a++) {
if(in[a] != v) {
copy[b] = in[a];
b++;
}
}
Using Java8 and it's streams feature you could do something like :
public static void main(String[] args) {
int[] array = {3236,47,34,34,73,46,3,64,473,4,4,346,4,63,644,4,6,4};
int[] newArray = removeAllOccurencesOf(array, 4);
System.out.println(Arrays.toString(newArray));
}
public static int[] removeAllOccurencesOf(int[] array, int numberToRemove)
{
//stream integers from array, filter the ones that correspond to number to remove, get what's left to new array
int[] newArray = IntStream.of(array).filter(i->i!=numberToRemove).toArray();
return newArray;
}
You can achieve the same result with some code like this:
// Add to params all inputs to remove from array
List<Integer> params = new ArrayList<>();
// Use Integer class instead of int datatype
Integer array[] = new Integer[] {0,1,2,3,4,3};
// Convert array to List class
List<Integer> list = new ArrayList<>(Arrays.asList(array));
// Remove all matches
list.removeAll(params);
I have for example this multidimensional array:
String[][] array = new String[10][2];
In the first column I have strings which are in my case usernames, but in the second column I have strings which should represent integers. Now I want to sort the array like this:
Before:
Petter 543
John 276
Jay 1879
Alf 5021
etc.
After:
Alf 5021
Jay 1879
Petter 543
John 276
etc.
So I want the highest value at the top and the lowest at the bottom but don't mess up the names. All I found till now is how to sort bother all integer multidimensional arrays or only string multidimensional arrays and not how to just sort the second column based on just integers.
I once got it sorted but it was sorted in "alphabetic" way:
So 1000 was the highest score
12 was the second highest score and
999999 was the lowest score.
Like 1 represents "a" and 9 represents "z".
Using Java 8 streams:
String[][] out = Arrays.stream(names)
.sorted(Comparator.comparing(x -> -Integer.parseInt(x[1])))
.toArray(String[][]::new);
If the person and the id are associated in some way, then it would be better to create a class that models them (POJO), make that POJO class comparable, define a list of the POJO and use Collections#sort to sorted according to the desired criteria...
another thing to consider is that you have a 2 dimentional String array
String[][] but your question states
...How to sort multidimensional string array by one column in integer value in java?
which means that you need to consider to parse the string to integer... (just as a nice hint)
public class MyPojo implement Comparator<MyPojo>{
private String name;
private String id;
...implements the method of the comparator
}
the do in the main test class
List<MyPojo> mList = new ArrayList<MyPojo>();
mList.add(...);
mList.add(...);
mList.add(...);
Collections.sort(mList);
System.out.println(mList)
Loop over the array until its sorted and swap each time it's not.
public static void main(String[] args) {
String[][] array = new String[4][2];
array[0][0] = "Petter"; array[0][1] = "543";
array[1][0] = "John"; array[1][1] = "276";
array[2][0] = "Jay"; array[2][1] = "1879";
array[3][0] = "Alf"; array[3][1] = "5021";
System.out.println(Arrays.deepToString(array)); // [[Petter, 543], [John, 276], [Jay, 1879], [Alf, 5021]]
sortArrayByScore(array);
System.out.println(Arrays.deepToString(array)); // [[Alf, 5021], [Jay, 1879], [Petter, 543], [John, 276]]
}
public static void sortArrayByScore(String[][] array) {
String tmpName, tmpScore;
boolean sorted = false;
while (!sorted) {
sorted = true;
for (int i = 0 ; i < array.length - 1 ; i++) {
if (Integer.parseInt(array[i][1]) < Integer.parseInt(array[i+1][1])){
sorted = false;
// SWAP NAMES
tmpName = array[i][0];
array[i][0] = array[i+1][0];
array[i+1][0] = tmpName;
// SWAP SCORES
tmpScore = array[i][1];
array[i][1] = array[i+1][1];
array[i+1][1] = tmpScore;
}
}
}
}
My advice would be to take the second column of the 2D array, and put it in its own integer array. Then, call Arrays.sort() on that array. Finally, place the newly sorted array back into the 2D array as string values. Here is what it should look like,
int arr = new int[10];
String[][] copy = new String[10][2];
for(int i = 0; i < array.length; i++){
arr[i] = Integer.parseInt(array[i][1]);
System.arraycopy(array[i], 0, copy[i], 0, array[i].length);
}
Arrays.sort(arr);
for(int i = 0; i < array.length; i++){
array[i][1] = String.valueOf(arr[i]);
}
//fixing the names
for(int i = 0; i < copy.length; i++){
for(int j = 0; j < array.length; j++){
if(copy[i][1] == array[j][1]){
array[j][0] = copy[i][0];
break;
}
}
}
EDIT: To address the order of the names, I changed the code to include a copy of the 2D array so that after rewriting the integer values in order, a check is done to see where each integer moved. For each integer, the corresponding name is transferred to where the integer moved.
Use a comparator to sort the items in an array. In your case you have an array of arrays so you need a comparator for an array. You can use a Comparator of String array which assumes the 2nd item is the value.
public class SomeComparator implements Comparator<String[]> {
/**
* Assumes each row is length 2 and the 2nd String is really a number.
*/
#Override
public int compare(String[] row1, String[] row2) {
int value1 = Integer.parseInt(row1[1]);
int value2 = Integer.parseInt(row2[1]);
// compare value2 first to sort descending (high to low)
return Integer.compare(value2, value1);
}
}
Then you can sort using Arrays.sort like this
String[][] data = newData(); // or however you get your data
Arrays.sort(data, new SomeComparator());
You can use a Comparator that sorts the inner String[] items on the Integer value of the second element, instead of using the default string sort:
Arrays.sort(array, (o1, o2) -> Integer.valueOf(o2[1]).compareTo(Integer.valueOf(o1[1])));
Here you are using lambda syntax to do the same as would be achieved by:
Arrays.sort(data, new Comparator<String[]>() {
#Override
public int compare(String[] o1, String[] o2) {
return Integer.valueOf(o2[1]).compareTo(Integer.valueOf(o1[1]));
}
});
Suppose I have an array of String like this
String [] item={"B","C","D","A"};
that means
item[0]=B
item[1]=C
item[2]=D
item[3]=A
Now I have sorted this array and gets like
item[0]=A
item[1]=B
item[2]=C
item[3]=D
I want to know the original index of element C(which is 1 here ) . How to find that using code? May be my question is not clear ,please ask me anything you did not understand .
You cannot unless you save some additinal data. You could e.g. put both index and value inside a class and sort by value, or you could define a array containing the indices and sort that array instead:
Integer[] indices = new Integer[item.length];
for (int i = 0; i < indices.length; i++) {
indices[i] = i;
}
Arrays.sort(indices, new Comparator<Integer>() {
public int compare(Integer i1, Integer i2) {
return item[i1].compareTo(item[i2]);
}
});
Sorted values:
item[indices[0]]
item[indices[1]]
item[indices[2]]
item[indices[3]]
Original indices
indices[0]
indices[1]
indices[2]
indices[3]
After you sorted your array. How can you trace your original position?
I come to mind just 3 options:
Save all the swaps you did during the sort process
Save an original copy of the vector
Use a structure where you save actual position and original position.
Recap: you have two arrays, unsortedArray and sortedArray. For each element of sortedArray, you want to retrieve the corresponding index in unsortedArray.
public int getCorrespondingIndex(String[] unsortedArray, String[] sortedArray, int index){
for(int i=0; i<unsortedArray.length; i++)
if(sortedArray[index].equals(unsortedAray[i])
return i;
return -1;
}
public static void main(String args[]){
int oldIndex;
String[] unsortedArray = {"B","C","D","A"};
String[] sortedArray= {"A", "B", "C", "D"};
for(i=0; i<sortedArray.length; i++){
oldIndex = getCorrespondingIndex(unsortedArray, sortedArray, i);
System.out.println("The element "+sortedArray[i]+" was in position "+oldIndex);
}
Before you sort the array use a map to store original indexes of your array elements as follows.
String[] item = { "B", "C", "D", "A" };
Map<String, Integer> map = new HashMap<String, Integer>();
for (int i = 0; i < item.length; i++) {
map.put(item[i], i);
}
when you need you call as follows
map.get("A"); // here return the original index of "A"
I'm learning and understanding Java now, and while practising with arrays I had a doubt. I wrote the following code as an example:
class example
{
public static void main(String args[])
{
String a[] = new String[] {"Sam", "Claudia", "Josh", "Toby", "Donna"};
int b[] = new int[] {1, 2, 3, 4, 5};
for(int n=0;n<5;n++)
{
System.out.print (a[n] + "...");
System.out.println (b[n]);
}
System.out.println (" ");
java.util.Arrays.sort(a);
for(int n=0;n<5;n++)
{
System.out.print (a[n] + "...");
System.out.println (b[n]);
}
}
In a nutshell, this class created two arrays with five spaces each. It fills one with names of characters from the West Wing, and fills the other with numbering from one to five. We can say that the data in these two strings corresponds to each other.
Now, the program sorts the array with the names in it using Arrays.sort(). After printing the array again, you can see that while the names are now in alphabetical order, the numbers do not correspond anymore as the second array is unchanged.
How can I shuffle the contents of the second array to match the sort requirements of the first? The solution must also be flexible to allow for changes in the scope and size of the program. Please do not post any answers asking me to change my methodology with the arrays, or propose a more 'efficient' way of doing things. This is for educational purposed and I'd like a straight solution to the example code provided. Thanks in advance!
EDIT: I do NOT want to create an additional class, however I think some form of sorting through nested loops might be an option instead of Arrays.sort().
Below is the code without using any Map Collection, but if you want to use Map then it becomes very easy. Add both the arrays into map and sort it.
public static void main(String args[]) {
String a[] = new String[] {
"Sam", "Claudia", "Josh", "Toby", "Donna"
};
int b[] = new int[] {
1, 2, 3, 4, 5
};
for (int n = 0; n < 5; n++) {
System.out.print(a[n] + "...");
System.out.println(b[n]);
}
System.out.println(" ");
//java.util.Arrays.sort(a);
/* Bubble Sort */
for (int n = 0; n < 5; n++) {
for (int m = 0; m < 4 - n; m++) {
if ((a[m].compareTo(a[m + 1])) > 0) {
String swapString = a[m];
a[m] = a[m + 1];
a[m + 1] = swapString;
int swapInt = b[m];
b[m] = b[m + 1];
b[m + 1] = swapInt;
}
}
}
for (int n = 0; n < 5; n++) {
System.out.print(a[n] + "...");
System.out.println(b[n]);
}
}
Some people propose making a product type. That is feasible only if the amount of elements is small. By introducing another object you add object overhead (30+ bytes) for each element and a performance penalty of a pointer (also worsening cache locality).
Solution without object overhead
Make a third array. Fill it with indices from 0 to size-1. Sort this array with comparator function polling into the array according to which you want to sort.
Finally, reorder the elements in both arrays according to indices.
Alternative solution
Write the sorting algorithm yourself. This is not ideal, because you might make a mistake and the sorting efficiency might be subpar.
You have to ZIP your two arrays into an array which elements are instances of a class like:
class NameNumber
{
public NameNumber(String name, int n) {
this.name = name;
this.number = n;
}
public String name;
public int number;
}
And sort that array with a custom comparator.
Your code should be something like:
NameNumber [] zip = new NameNumber[Math.min(a.length,b.length)];
for(int i = 0; i < zip.length; i++)
{
zip[i] = new NameNumber(a[i],b[i]);
}
Arrays.sort(zip, new Comparator<NameNumber>() {
#Override
public int compare(NameNumber o1, NameNumber o2) {
return Integer.compare(o1.number, o2.number);
}
});
You should not have two parallel arrays. Instead, you should have a single array of WestWingCharacter objects, where each object would have a field name and a field number.
Sorting this array by number of by name would then be a piece of cake:
Collections.sort(characters, new Comparator<WestWingCharacter>() {
#Override
public int compare(WestWingCharacter c1, WestWingCharacter c2) {
return c1.getName().compareTo(c2.getName();
}
});
or, with Java 8:
Collections.sort(characters, Comparator.comparing(WestWingCharacter::getName));
Java is an OO language, and you should thus use objects.
What you want is not possible because you don't know internally how Arrays.sort swap the elements in your String array, so there is no way to swap accordingly the elements in the int array.
You should create a class that contains the String name and the int position as parameter and then sort this class only with the name, providing a custom comparator to Arrays.sort.
If you want to keep your current code (with 2 arrays, but this not the ideal solution), don't use Arrays.sort and implement your own sorting algorithm. When you swap two names, get the index of them and swap the two integers in the other array accordingly.
Here is the answer for your query.
public class Main {
public static void main(String args[]){
String name[] = new String[] {"Sam", "Claudia", "Josh", "Toby", "Donna"};
int id[] = new int[] {1, 2, 3, 4, 5};
for ( int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int dtmp=0;
String stmp=null;
if (id[i] > id[j]) {
dtmp = rate[i];
id[i] = id[j];
id[j] = dtmp;
stmp = name[i];
name[i]=name[j];
name[j]=stmp;
}
}
}
System.out.println("Details are :");
for(int i=0;i<n;i++){
System.out.println(name[i]+" - "+id[i]);
}
}
}
The same solution, as a function that can be added to some utils class:
public static final boolean INCREASING = true;
public static final boolean DECREASING = false;
#SuppressWarnings("unchecked")
public static <T extends Comparable, U extends Object> void bubbleSort(ArrayList<T> list1, ArrayList<U>list2, boolean order) {
int cmpResult = (order ? 1 : -1);
for (int i = 0; i < list1.size() - 1; i++) {
for (int j = 0; j <= i; j++) {
if (list1.get(j).compareTo(list1.get(j+1)) == cmpResult) {
T tempComparable = list1.get(j);
list1.set(j , list1.get(j + 1));
list1.set(j + 1 , tempComparable);
U tempObject = list2.get(j);
list2.set(j , list2.get(j + 1));
list2.set(j + 1 , tempObject);
}
}
}
}
The arrays are not linked in any way. Like someone pointed out take a look at
SortedMap http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html
TreeMap http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html
import java.util.*;
class mergeArrays2
{
public static void main(String args[])
{
String a1[]={"Sam", "Claudia", "Josh", "Toby", "Donna"};
Integer a2[]={11, 2, 31, 24, 5};
ArrayList ar1=new ArrayList(Arrays.asList(a1));
Collections.sort(ar1);
ArrayList ar2=new ArrayList(Arrays.asList(a2));
Collections.sort(ar2);
System.out.println("array list"+ar1+ " "+ar2);
}
}
List<Data> list = new ArrayList<Data>();
public class Data{
public int n;
public String p;
public Data(int N, String P) {
n = N;
p = P;
}
}
How can i shuffle the Integer of the Object: Data. So the String stays at the same position, and the Integer get's shuffled.
Loop through list and store the int of each Data object in a separate list. Shuffle this list using Collections.shuffle(...). Loop through this new shuffled list and set the n field of each corresponding member of list to the new random int found in the shuffled list.
Probably have to do it yourself:
for (int i = list.size(); i > 0; i--) {
int j = (int)(Math.random() * (i + 1));
int temp = list.get(i).n;
list.get(i).n = list.get(j).n;
list.get(j).n = temp;
}
The best you can do from java libraries is to first split it into two lists, one of ints and one of strings, then shuffle only the ints (using Collections.shuffle), then combine the two lists back into one list of Datas
You could use something like this:
List<Integer> ns = new ArrayList<Integer>(list.size());
for (Data data : list) {
ns.add(data.n);
}
Collections.shuffle(ns);
for (int i = 0; i < list.size(); i++) {
Data data = list.get(i);
int newN = ns.get(i);
data.n = newN;
}
Note that it's best practice to use accessors getN() and setN(int) and make Data.n private.