2013-10-01 7 views
5

Ho una stringa di lettere maiuscole e numeri che devo "logicamente" ordinare e archiviare in un campo in un database. Ho ottenuto l'aggiornamento/modifica/richiesta di informazioni nel database capito. Sono in difficoltà con l'ordinamento logico di questa stringa.ordinamento logico di una stringa mista di lettere maiuscole e numeri

Ecco, spero di poterlo spiegare bene.

Dato questo insieme di stringhe AB1 AB2 AB3 A11 AB10

Ho bisogno di questi per alpha specie in questo modo

A11 AB1 AB2 AB3 AB10

al fine per raggiungere questo, credo di aver bisogno di esplodere la stringa. perché attualmente sto cercando di ottenere risultati alfabetici A11 AB1 AB10 AB2 AB3

MODIFICA: Devo essere in grado di memorizzare una stringa esplosa e una stringa non esplosa per poter ordinare con altri programmi.

Ecco come credo che hanno bisogno di essere spezzata e conservati al fine di risolvere alfa

A11 - A 11 
AB1 - AB 1 
AB2 - AB 2 
AB3 - AB 3 
AB10 - AB 10 

Ci sono alcune costanti. La stringa non sarà più grande di 5 posizioni. Conterrà solo lettere maiuscole e numeri.

Ecco quanto ho ottenuto con il mio codice. gli scrittori bloccano quindi spero in qualche aiuto. Penso di aver bisogno di trovare se inizia con una lettera, poi trovare tutte le lettere consecutive, spostare quelle a sinistra, poi andare a lavorare sul numero, trovare tutti i numeri consecutivi e spostare quelli allineati a destra. Non sono sicuro di come qualcosa di simile a 'A1B1' avrebbe funzionato o ...

for(int ii = 0;ii < sectionString.length() && ii< SECTIONSPACES;ii++){ 
       System.out.print(" Was previous a number? " + isPreviousANumber +   "\n"); 
try{ 
    String tmpString = sectionString.substring(ii,ii + 1); 
    int positionInCharArray = Integer.parseInt(tmpString); 
    System.out.printf(" Position " + ii + " is number " + positionInCharArray + "\n"); 
    isPreviousANumber = true;   
}catch(Exception e){ 
    System.out.printf(" Position " + ii + " number is not a number " +  sectionString.substring(ii,ii) + "\n"); 
    isPreviousANumber = false; 
    }     
} 
+0

Impiegare qualcosa di simile all'ordinamento digitale con cifre che hanno la precedenza sulle lettere. – arynaq

+0

Copierò un commento che ho fatto di seguito. Funziona benissimo per ordinarli se posso usare java per ordinarli. Il problema è che i diversi programmi devono ordinarli e per essere compatibili con essi, ho bisogno di "esplodere" la stringa e usare la stringa esplosa per ordinare e mostrare semplicemente il valore normale. Non 'normale' lo so. Nel db ci saranno due campi, uno sarà chiamato sezione e un campo chiamato sort_section. Ha senso? – nkuebelbeck

risposta

1

Questa osservazione "Non sono sicuro di come qualcosa di simile a 'A1B1' avrebbe funzionato o ..." aumenta in qualche modo la complessità del problema. Il seguente dovrebbe funzionare per tutti i casi.

Metodo:

Divide la stringa in token. Un token è una lettera o una serie di cifre consecutive. Riempi ciascun token numerico a cinque caratteri con spazi iniziali. Concatena i token per creare la stringa esplosa.

Da un originale di 5 caratteri, la stringa esplosa più lunga sarà di 17 caratteri.

Le stringhe esplose risultanti possono essere ordinate da qualsiasi programma o da una clausola SQL "ORDERED BY".

Esempi:

1A1A1 " 1A 1A 1" 
11A11 " 11A 11" 
1111A " 1111A" 
11111 "11111" 
A1  "A 1" 
A1B1 "A 1B 1" 
A1C  "A 1C" 
A2  "A 2" 
A2B1 "A 2B 1" 
A10  "A 10" 
A10B1 "A 10B 1" 
A11  "A 11" 
AA1  "AA 1" 
AB1  "AB 1" 
AB2  "AB 2" 
AB10 "AB 10" 
ABC  "ABC" 

Pseudocodice:

// original = "section" string 
exploded = "" 
prevdigits = false 
for ii from 1 to length(original) { 
    ch = original[ii] 
    if (ch is a digit) then { 
     if not prevdigits then { 
     token = "" 
     prevdigits = true 
     } 
     token = token+ch 
    } else { // letter 
     if prevdigits then { 
     exploded = exploded + spaces(5-length(token)) + token 
     prevdigits = false 
     } 
     exploded = exploded + ch 
    } 
} 

-Al.

+0

Il mio male per aggiungere in quell'ultima osservazione. Ho appena capito la stessa cosa e stavo tornando ad aggiornare con il mio codice. – nkuebelbeck

0

vorrei completare queste stringhe con gli spazi a 5 simboli e dopo che farebbe Radix Sort. Possiamo confrontare tutti i simboli come caratteri.

String[] array = {"A11", "AB1", "AB2", "AB3", "AB10"}; 

    int i, j, length; 
    for (i = 0; i < array.length; i++) { 
     length = array[i].length(); 
     for (j = length; j < 5; j++) { 
      array[i] += " "; 
     } 
    } 

    Arrays.sort(array); 

    for (int k = 0; k<array.length; k++) 
     System.out.println(array[k]); 
1

Ecco come posso ordinare utilizzando il mio radix sort idea:

public static String[] radixSort(String[] strings){ 
    // Pad the strings 
    for(int i=0; i<strings.length; i++){ 
     strings[i] = String.format("%-5s", strings[i]); 
    } 

    // Radix sort them 
    for (int digit = 0; digit < 5; digit++) { 
     final int i = digit; 
     Arrays.sort(strings, new Comparator<String>() { 


      @Override 
      public int compare(String o1, String o2) { 
       return o1.charAt(i) - o2.charAt(i); 
      } 
     }); 
    } 

    // Then trim the whitespaces we used to pad 

    for (int i = 0; i < strings.length; i++) { 
     strings[i] = strings[i].trim(); 
    } 

    return strings; 
} 

Con ingresso

String[] strings = new String[] { "AB1", "AB2", "AB3", "A11", "AB10" }; 
    System.out.println(Arrays.toString(radixSort(strings))); 

E uscita

[A11, AB1, AB2, AB3, AB10] 

io non sono sicuro che questo è il metodo più efficiente ma ottiene il lavoro.

+0

Questi funzionano benissimo per ordinarli se posso usare java per ordinarli. Il problema è che i diversi programmi devono ordinarli e per essere compatibili con essi, ho bisogno di "esploderli" e usare la stringa esplosa per ordinare e mostrare semplicemente il valore normale. Non 'normale' lo so. Nel db ci saranno due campi, uno sarà chiamato sezione e un campo chiamato sort_section. Ha senso? – nkuebelbeck

+0

Non era a conoscenza del secondo requisito, avvolgendoli in un altro oggetto come suggerito da Marco sarebbe la strada da percorrere allora, con getter aggiunti o usare regex per dividere le stringhe che ordino in valori alfa e numerici. – arynaq

+0

quello era il mio cattivo, ho aggiunto quel requisito nel post originale – nkuebelbeck

1

potresti usare un'altra classe come rappresentazione speciale per le tue stringhe. qualcosa di simile:

public class AlphaNumericString implements Comparable<AlphaNumericString> { 
    public final String alphaPart; 
    public final Long numericPart; 

    public AlphaNumericString(String string) { 
     int index = 0; 
     while (index < string.length() && !Character.isDigit(string.charAt(index))) { 
      index++; 
     } 

     alphaPart = string.substring(0, index); 

     if (index < string.length()) { 
      numericPart = new Long(string.substring(index)); 
     } else { 
      numericPart = null; 
     } 
    } 

    @Override 
    public int compareTo(AlphaNumericString other) { 
     int stringCompareResult = alphaPart != null ? alphaPart.compareTo(other.alphaPart) : -1; 

     if (stringCompareResult == 0) { 
      return numericPart != null ? numericPart.compareTo(other.numericPart) : -1; 
     } else { 
      return stringCompareResult; 
     } 
    } 

    @Override 
    public String toString() { 
     return (alphaPart != null ? alphaPart : "") + (numericPart != null ? numericPart : ""); 
    } 
} 

È possibile attivare le corde attuali in questa classe, genere e li converte di nuovo, se necessario

0

Ecco il mio codice. Sono sicuro che può essere semplificato, è stato uno di quei momenti di oscuramento in cui ho avuto un bambino cervello e avevo bisogno di scrivere. Questo non avrebbe funzionato se la stringa di numeri era finita lunga 5 caratteri ...

aggiornamento: meno brutta

private String buildPieceSortNumber(String pieceNumber){ 
    final int INTSPACES = 5; 
    final String SPACE = " "; 
    String explodedSection = "";   
    char[] charArray = pieceNumber.toCharArray(); 
    String ints = ""; 
    for(int i = 0;i < charArray.length;i++){ 
     if(Character.isDigit(charArray[i])){ 
      //add to the int string 
      ints += charArray[i]; 
      //check if the next character in the array is a number 
      int nextChar = i + 1; 
      //make sure we don't go past the end of the string     
      if(nextChar < charArray.length){ 
       if(!Character.isDigit(charArray[nextChar])){ 
        //end of numbers, take ints string, and add padding up to five positions 
        while(ints.length() < INTSPACES){ 
         ints = SPACE + ints; 
        } 
        //add the int string to the end of the exploded string 
        explodedSection += ints;       
        //clear the int string 
        ints = ""; 
        } 
      }else{ 
       //end of numbers, take ints string, and add padding up to five positions 
       while(ints.length() < INTSPACES){ 
        ints = SPACE + ints; 
       } 
       //add the int string to the end of the exploded string 
       explodedSection += ints; 
       //clear the int string 
       ints = ""; 
      }     
     }else{ 
      explodedSection += charArray[i];                
     } 
    } 
    return explodedSection; 
0

Avete veramente bisogno di ordinare i dati prima di metterlo nel database? Considera di lasciare che il database faccia il lavoro per te.

Supponi di aver scritto il valore direttamente nel database. Il tuo database potrebbe permetterti di fare qualcosa come il mio. In DB2, per ottenere solo lettere, tradurrei tutte le cifre in spazi e quindi rimuovere tutti gli spazi. Lo stesso concetto può essere applicato per ottenere solo cifre.

SELECT replace(translate(inp, @spaces, @digits),' ','') as alpha, 
     int(replace(translate(inp, @spaces, @letters),' ','')) as nbr, 
     .... 

Anche se questo potrebbe essere un approccio database normalizzato, si potrebbe in dubbio l'esecuzione di questo calcolo ogni volta i dati vengono recuperati dalla tabella. Così, invece, fare questo quando si scrive i dati nella tabella

INSERT INTO yourtable (item, alpha, nbr, .....) 
    VALUES (inp, 
      replace(translate(inp, @spaces, @digits),' ',''), 
      int(replace(translate(inp, @spaces, @letters),' ','')), 
      ..... 
      ) 

A mio avviso, questa è la logica più semplice, meno codice, più facile da testare/debug, contribuendo a ridurre i rischi di difetti, e di essere più facile per qualcuno a mantenere. Ovviamente il tuo chilometraggio può variare a seconda del tuo database. Ma questo approccio sembra degno di considerazione.

Problemi correlati