Domanda

Il mio Java è estremamente arrugginito e mi sono bloccato cercando di fare un'interfaccia utente che semplifica l'esecuzione di script di shell o file batch a seconda che si tratti di rispettivamente Linus o Win32. I file hanno la seguente convenzione di denominazione.

  module-verb-object-etc [args-list]
  mysql-connect-grid
  mysql-connect-rds
  mysql-dump-grid
  mysql-dump-grid-se314

in ultima analisi, vorrei che per analizzare termini inequivocabili così posso:

  1. tokenize i comandi (es delimitati da "-") e li abbreviare in termini semplificati soemthing come finestra di comando FoxPro o IOS CISCO (ad esempio "mio co gr" esegue "mysql-connect-griglia" in unix e * cmd in win32)
  2. e anche nello stile di IOS consente all'utente di inserire i comandi abbreviati in modo che possano digitare un punto interrogativo (?) E si darà loro un suggerimento per quanto riguarda la unica rimanente (o successivo) le opzioni di comando (ad esempio " il mio?" restituisce mysql e 'i miei?' ritorni collegano, o discarica). valori restituiti OTHR sarebbe "ambiguo" o "sconosciuto" per i comandi che non sono unici o non poteva essere eguagliata. Può sembrare banale, ma ci sono molte centinaia di comandi in ogni cartella e fare i miei utenti non voglio pensare ...

ho scritto una funzione per estrarre l'elenco dei file da una directory e retun una serie di fileanmes. Poi converte che in una matrice bidimensionale 2 utilizzando il seguente metodo che restituisce una griglia dynamicly dimensioni di eventuali comandi.

    /**********************************************************************************
     *  MAKE GRID: Parses array of filenames and tokenizes AWS cmds.
     * @param strs  Array of filenames
     **********************************************************************************/
     public static String [][] makeGrid(String strs[], boolean bPrint) {
       String tmpGrid[][];
       int nMaxCols = 0;
       int nRows = uniqueCount(strs);
       int nGridRow = 0; 
       tmpGrid = new String [nRows][]; 
       for (int nRow=0; nRow<nRows; nRow++) { 
 String cFilename = strs[nRow];
                if (!cFilename.endsWith(".cmd") // just list unix files (filter for batch files)
    && cFilename.indexOf("-") > 0 ) // make sure there's a dash in the filename
    {
           String strTokens[] = tokenize(strs[nRow], "-"); // the dash is our token deliminator
           int nCols = strTokens.length; 
           if (nCols>nMaxCols) nMaxCols=nCols;
           tmpGrid[nGridRow] = new String [nCols];
           for (int nCol=0; nCol<nCols; nCol++) { 
               tmpGrid[nGridRow][nCol] = strTokens[nCol];
               if (bPrint) System.out.print(" "+tmpGrid[nGridRow][nCol]);
             }
            nGridRow++;
            if (bPrint) System.out.println("");
     } //end-if
         }
       String[][] cmdGrid = new String[nGridRow][nMaxCols];
       System.arraycopy(tmpGrid, 0, cmdGrid, 0, nGridRow); // removes null rows  (&NPEs!)
       return cmdGrid;
      }

Questo restituisce una matrice 2-D (sotto), quindi grid[Row-N][Col-0] è una partita. Mi piacerebbe tirare solo valori distinti dove row[0] è una partita jolly per cmdToken[0] && row[1] è "come" cmdToken[1] in modo che i miei utenti possono mettere insieme un comando fino "my du gr ?" ritorna "ENTER, [se314]" - se questo ha un senso ...

String[][] makeGrid:
    mysql dump grid se314
    mysql connect grid
    mysql dump grid
    mysql connect rds

La mia sfida: I cant sembrano ottenere la mia testa intorno la mia funzione matcher in java. Se fosse SQL sarebbe qualcosa di simile:

"SELECT DISTINCT col2 FROM cmd_Grid
   WHERE col1 LIKE 'cmdToken1%' " 

o meglio: impostazione ricorsivamente un int depthmark per ogni colonna consecutiva

`SELECT DISTINCT col+str(depthmark+1) FROM cmd_Grid 
    WHERE col+str(depthmark) LIKE 'cmdMatchedTokens%' " 

fino ad avere una corrispondenza esatta.

Ho trovato un pacchetto chiamato joSQL che ho provato per disperazione, ma smusso sembro farlo funzionare in java6. Ad ogni modo: Sono stato anche sperando in una soluzione Java puro in modo che tutto possa far parte di una singola classe ...

Forse usando scanner o qualcosa di analizzare la mia matrice multidimensionale per i valori unici ... So che probabilmente sto facendo è molto più complesso di quello che deve essere.

una gomitata dolce nella giusta direzione sarebbe apprezzato.

TIA

È stato utile?

Soluzione

Una soluzione potrebbe essere esaustivo a contruct un HashMap in modo che la chiave è una possibile breve comando come 'mio co gr" e il corrispondente valore è 'mysql-connettono-griglia'. Quindi ci sarebbero valori nella mappa di hash che avrà "mysql-connect-grid" come valore.

Ma questa è una soluzione praticabile solo se v'è un numero finito di possibili chiavi. Se questo non è il caso, quindi è possibile utilizzare il costruito nel metodi all'analisi delle stringhe.

Ad esempio:

    String[][] makeGrid = new String[][]{{"mysql", "dump", "grid", "se314"}, 
              {"mysql", "connect", "grid", ""},
              {"mysql",  "dump", "grid", ""},
              {"mysql", "connect", "rds", ""}
              };
     String[] query2 = new String[]{"my", "du", "gr"};

  String[][] matchingCommands = new String[4][4];
  int resultSize = 0;
     for(int i=0; i<makeGrid.length; i++)
  {
      String[] commandColumn = makeGrid[i];
   boolean matches = false;
      for(int cnt=0; cnt<commandColumn.length; cnt++)
      {
       String commandPart = commandColumn[cnt];
       if(cnt < query2.length){
        String queryPart = query2[cnt];
     if(commandPart.startsWith(queryPart) || queryPart.equals("?")){
         matches = true;
        }else{
         matches = false;
         break;
        }
       }
      }
      if(matches){
       matchingCommands[resultSize] = commandColumn;
       resultSize++;
      }
  }

Questo frammento di codice dovrebbe darvi qualche idea di come andare a questo proposito. C'è una cosa da notare qui però. Il matchingCommands array è stato inizializzato a 4 righe e 4 colonne, che è uno spreco perché le partite sarà minore di quello. Fammi sapere se hai bisogno di aiuto rendendo questo più efficiente. In caso contrario, questo è un pezzo di lavoro di codice che credo non ciò che si desidera.

Altri suggerimenti

Si potrebbe anche prendere in considerazione l'utilizzo di alcune strutture di dati più avanzate come un ArrayList invece di un array e utilizzare lo StringTokenizer per generare ogni comando Parte al volo.

Sarà qualcosa di simile:

ArrayList<String> matchingCommands = new ArrayList<String>();

    ArrayList<String> commandList = new ArrayList<String>();
    commandList.add("mysql dump grid se314");
    commandList.add("mysql connect grid");
    commandList.add("mysql dump grid");
    commandList.add("mysql connect rds");

    String queryCommand = "my du gr ?";

    for(int i=0; i<commandList.size(); i++)
    {
        boolean matches = false;
        String command = commandList.get(i);
        StringTokenizer commandTokenizer = new StringTokenizer(command, " "); // Using space as the deliminator
        StringTokenizer queryTokenizer = new StringTokenizer(queryCommand, " "); // Using space as the deliminator

        while(commandTokenizer.hasMoreTokens())
        {
            String queryPart = queryTokenizer.nextToken();
            String commandPart = commandTokenizer.nextToken();
            if(commandPart.startsWith(queryPart) || queryPart.equals("?")){
                matches = true;
            }else{
                matches = false;
                break;
            }
        }
        if(matches){
            matchingCommands.add(command);
        }
    }
    System.out.println(matchingCommands);

Questo avrebbe fatto in modo che il programma possa crescere in modo dinamico e non c'è spreco di memoria a causa di oggetti nulli sia.

in questo momento stavo giocherellando in giro con l'analisi di ogni cmdstring (query) per il delimitatori bianco-spazio e creazione di token l'array. Qualcosa di simile:

 Scanner sCmdString = new Scanner(cInput);
 while (sCmdString.hasNext()) { 
 String cToken = sCmdString.next().toUpperCase().trim();
 System.out.println(" "+cToken+" ");
 // match cmdString[i..n] to cmdGrid
 for (int nRow=0; nRow < cmdGrid.length; nRow++) {
       for (int nCol=0; nCol < cmdGrid[nRow].length; nCol++) {
  if (cmdGrid[nRow][nCol].equalsIgnoreCase(cToken) )
     System.out.println("MATCH: "+cmdGrid[nRow][nCol]);
  else System.out.println("NO MATCH:"+cmdGrid[nRow][nCol].toUpperCase()+":"+cToken+"...");
        }
   }
   }

ma mi è stato sempre NPE con le lunghezze delle righe irregolari.

E mi piace la vostra idea di appiattimento delle colonne.

Penso che avrei ancora per rimuovere i duplicati ... no?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top