5

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().

Vedant Chandra
  • 342
  • 2
  • 3
  • 15
  • 1
    Take a look at SortedMap http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html – cangrejo Apr 28 '14 at 10:50
  • 1
    Is it mandatory to use java.util.Array.Sort() only? Why don't you just write your sort method? – Selvin Apr 28 '14 at 10:51
  • Its possible with a custom sort method. – Selvin Apr 28 '14 at 10:52
  • There is no information **link** between a and b, so it is not possible. Is using a `Map` also forbidden for this particular educational purpose? – tkokasih Apr 28 '14 at 10:58
  • 1
    Writing ambiguous and unclear code doesn't sound to me as an "educational purpose". Create additional object and do it properly. – Jakub H Apr 28 '14 at 10:59
  • 1
    You're not understanding me, I'm not doing this just to solve my problem, I want to discover a way of sorting the arrays together using just loops. For me learning isn't just about finding a solution to a problem, it's learning all the possible solutions. – Vedant Chandra Apr 28 '14 at 11:01
  • For all the downvotes on my question, could you tell me where I went wrong and how I can avoid it next time? – Vedant Chandra Apr 29 '14 at 09:38
  • This question makes sense when you have a very big amount of primitive data that you want to sort very fast without the cost of a boxing object. It's a pity you have to make your own sort code in that case. If your amount of data is "normal" however, don't use two arrays, but one of a boxing object. – Arnaud Feb 13 '15 at 14:41
  • Actually you do not have to make your own sort in the case you have huge arrays. Simply make a "index" array than you sort instead of your actual arrays (using a custom comparator) – Arnaud Feb 13 '15 at 14:49
  • Have a look at `it.unimi.dsi.fastutil.Arrays.quickSort` (http://fastutil.di.unimi.it/docs/it/unimi/dsi/fastutil/Arrays.html). It allows you to sort your two arrays by specifying the swap() method. – Arnaud Feb 13 '15 at 16:02

9 Answers9

11

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]);
    }
}
Shiva
  • 6,677
  • 4
  • 36
  • 61
Prashant Gurav
  • 505
  • 7
  • 17
  • Thank you so much, this works perfectly and I now know how to use bubble sort. – Vedant Chandra Apr 28 '14 at 11:57
  • Would you mind posting a Gist or Pastebin with the bubble sort loops taking 'n' array spaces instead of 5? – Vedant Chandra Apr 28 '14 at 13:21
  • 1
    for(int i = 0 ; i < n ; i ++) for (int m = 0 ; m < n - i - 1 ; m ++) – Prashant Gurav Apr 28 '14 at 13:59
  • @PrashantGurav, is it possible to obtain the sorted index so that the original order can be restored using such index afterwards? – XYZ Mar 03 '21 at 08:39
  • @PrashantGurav, I figured it out, adding `int[] idx = new int[a1len]; Arrays.setAll(idx, i -> i );` and sort `idx` together with `b` will return the index of the sorted array. – XYZ Mar 03 '21 at 08:53
11

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.

Rok Kralj
  • 46,826
  • 10
  • 71
  • 80
2

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);
    }
});
Community
  • 1
  • 1
1

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.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

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.

Alexis C.
  • 91,686
  • 21
  • 171
  • 177
  • This is the most relevant answer till now, do you have any ideas as to how I could sort the arrays using loops? – Vedant Chandra Apr 28 '14 at 11:02
  • @VedantChandra You can look at some implementations of sorting algorithm (I would start with the most simple, called bubble sort http://en.wikipedia.org/wiki/Bubble_sort). This is not really efficient but simple to implement. When you'll done that you could start to implement more efficient sorting algorithms. – Alexis C. Apr 28 '14 at 11:02
  • Bubble sorting sounds perfect, how can I go about implementing this is my code? – Vedant Chandra Apr 28 '14 at 11:07
  • @VedantChandra The wikipedia page provides all the necessary informations to implement it. IMO this is clearly better for you to learn how to implement it (this is not hard) than for me to write the code for you. All you have to know is that for comparing objects in Java, they have to implement the comparable interface (this is the case for `Strings`) and you use the `compareTo` method instead of < or >. – Alexis C. Apr 28 '14 at 11:09
  • @VedantChandra You could write a first method that takes a String array as parameter. Then a more generic one using generics with the appropriate bounds to ensure that the elements are comparable. You can look at this question I answered, which was basically the same problem as you. http://stackoverflow.com/questions/20270336/array-sort-multidimensional-array-to-match-second-array/20270506 – Alexis C. Apr 28 '14 at 11:11
0

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]);
        }
    }
}
JensS
  • 1,151
  • 2
  • 13
  • 20
0

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);
      }
    }
  }
}
-1

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

NRKirby
  • 1,584
  • 4
  • 21
  • 38
-1
   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);
  }

}
Gaurav londhe
  • 199
  • 1
  • 4