Link to home
Start Free TrialLog in
Avatar of Tore
ToreFlag for Norway

asked on

Search for string in 2 dimensional string array

This relates to a previous question ( .. i forgot to get an answer before i closed it :( ) 


How do i search for a string in a 2 dim string array (column 0)

I have the following 2 dim string table. It is sorted by its first column.

I then thought i could use a Array.binarySearch (works fine for a one dimensional array) but i can't get my head around on how to do it on a 2 dim.

I need some expert advice.


import java.util.Arrays;
import java.util.Comparator;

public class TwoDimStringTable {
    
    public static void main(String [] args) {
        int i = 0;
        
        String[][] sTabell = new String[8][2];
        sTabell[0][0] =  "Ola";                sTabell[0][1] =  "Ola";
        sTabell[1][0] =  "var";                sTabell[1][1] =  "kunne";
        sTabell[2][0] =  "fra";                sTabell[2][1] =  "engelsk";
        sTabell[3][0]=   "Sandefjord";         sTabell[3][1]=   "ei";
        sTabell[4][0] =  "Han";                sTabell[4][1] =  "men";
        sTabell[5][0] =  "var";                sTabell[5][1] =  "han";
        sTabell[6][0] =  "lettmatros";         sTabell[6][1] =  "klarte";
        sTabell[7][0] =  "ombord!";            sTabell[7][1] =  "seg";

        for ( i = 0; i <= sTabell.length-1; i++) {
            System.out.println(sTabell[i][0] + "  " + sTabell[i][1]);
        }
        
        System.out.println(Arrays.deepToString(sTabell));
        for (i = 0; i < sTabell.length; i++) {
            Arrays.sort(sTabell[i]);
        }
        System.out.println(Arrays.deepToString(sTabell));
        Arrays.sort(sTabell, new Comparator<String[]>() {
            
            public int compare(String[] r1, String[] r2) {
                return Arrays.compare(r1, r2);
            }
        });
        System.out.println(Arrays.deepToString(sTabell));
        
        for ( i = 0; i <= sTabell.length-1; i++) {
            System.out.println("i = " + i + " " + sTabell[i][0] + "  " + sTabell[i][1]);

         // Question: how to get index of string "Sandefjord"

        }
      }
   }

Open in new window

Avatar of krakatoa
krakatoa
Flag of United Kingdom of Great Britain and Northern Ireland image

You already have the loop for that. So you can do :

if(sTabell[i][0].equals("Sandefjord")){System.out.println("Sandefjord found at "+i);}

Open in new window

after the sort() of course.
The problem with a binary search is that the array/collection must be sorted first. If, as you are, you are sorting by row, then the search token would have to be a whole row, not just a string in a row. What is your requirement – to find the indices of a complete string, or a partial string?
An iterative approach is probably right. Try
    public static int[] findMatch(String[][] table, String pattern) {
        int[] result = { -1, -1 };
        for (int row = 0; result[0] < 0 && row < table.length; row++) { 
            for (int col = 0; result[1] < 0 && col < table[row].length; col++) {
                if (table[row][col].matches(pattern)) {
                    result[0] = row;
                    result[1] = col;
                }
            }
        }
        return result;
    }

Open in new window

Avatar of Tore

ASKER

Thanks CEHJ
The main idea was to create the fastest serch, and binarySearch seems to be a quick one (hence the sorting).
Your suggestion is a sequential search so sorting gives no benefit.

When you say the search token needs to be the whole row, how will that look like in a binary search (to take advantage of the sorting).
The row in question holds "Sandefjord" and "ei" (column 0 an 1)

Appreciate your patience :)

ASKER CERTIFIED SOLUTION
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Tore

ASKER

not a real world problem yet,  but what would you suggest for eg 5000 rows with names like this read from a database ?
You would run that search on the database
Multidimensional arrays - apart from maybe holding co-ordinates for graphic applications or some maths operations - seem to me to be a bit of a throwback to the days when less sophisticated tools were available. So although I don't have any more interesting insight than that, I am making this comment because, as has been said, it's not completely clear what it is you are trying to achieve - with database involvement or without. Why are you holding such a small amount of related data in this form ? I'm not getting involved in the database conversation, because I don't tread in that territory, but in OOP terms I would venture to say that a more conventional approach would be to hold this dimensioned data as objects with multiple fields of a class. What would an entry like :

Sandefjord  ei

be doing floating around on its own ? Maybe I've missed something, or you have another particular aim in mind that I can't see.
Avatar of Tore

ASKER

@both:
The above is more like a test on how to do it.
I.e. how to create and navigate in a 2dim string table/data structure and how to do a binary search.
What would be the most efficient data structure to do this in Java (i.e. not involving a database)?

Well, as I've indicated above, a binary search is not really practicable. You would have to know the whole row to be able to call a binary search on it. If you knew the whole row, then you'd presumably also know what its position was…
Avatar of Tore

ASKER

OK CEHJ
Thanks for the update. Appreciated :)
Case closed for now.
In case you inadvertently 'left early' again, I thought you might like to see my take on the OOP paradigm that I commented on, (money where my mouth was stuff) which holds individual pairs of your String array variables in single Objects (Twin, for want of a better class name), and maintains the array of those Twins in a separate class object called Creator (again for want of a better name).

Once the twins are created and stored in a HashSet, (so you can't have two identical entries), they can be sorted (in my approach, I decided to use an array). The first sort() will produce a first-field sort, and the second routine will do a subsort on the second field.


import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator ;
import java.util.HashSet ;


public class Creator {

    public static void main(String [] args) {
    
             int place = 0;
    
             HashSet<Twin> ts = new HashSet<Twin>() ;
           
             Twin twin = new Twin("Ola","var");ts.add(twin);
             twin = new Twin("fra","Sandefjord");ts.add(twin);
             twin = new Twin("Han","var");ts.add(twin);
             twin = new Twin("lettmatros","ombord!");ts.add(twin);
             twin = new Twin("Ola","kunne");ts.add(twin);
             twin = new Twin("engelsk","ei");ts.add(twin);
             twin = new Twin("klarte","han");ts.add(twin);
             twin = new Twin("Ola","seg");ts.add(twin);
             
             Iterator it = ts.iterator();
             
             Twin[] twa = new Twin[ts.size()];
             
             while(it.hasNext()){twa[place++]=(Twin)it.next();}
            
                    
            Arrays.sort(twa, new Comparator<Object>() {      
        
                public int compare(Object a, Object b) {
              
                    return (((Twin)a).first.compareToIgnoreCase(((Twin)b).first));
                    
                }
            });
            
            /*** Include the routine below if a subsort (i.e. on the second field) is required.
            */
            Arrays.sort(twa, new Comparator<Object>() {      
        
                public int compare(Object a, Object b) {
              
                    if(((Twin)a).first.equals(((Twin)b).first)){
                        return (((Twin)a).second.compareToIgnoreCase(((Twin)b).second));
                    }
                    else{return ((Twin)a).first.compareToIgnoreCase(((Twin)b).first) ;}
                }
            });
            

            for (int i = 0; i < twa.length; i++) {
            
            System.out.println(twa[i].first+" "+twa[i].second) ;
            
            } 
              
      }   
}



 class Twin {


 public String first ;
 public String second ;


 public Twin(String f, String s){

    this.first = f ;
    this.second = s ;

 }

 public Twin(){}

 }

Open in new window


I've put both classes in the same file, to make it easier.
 
Avatar of Tore

ASKER

Thanks a lot krakatoa !
Very useful sample :)

I have to admit that I in the end ended up with a HashMap structure to solve my issue (as there was a few other additional things to include in the code )
Thanks !