2015-07-07 18 views
7

Dato un array di valori int, come si può analizzare la serie nella notazione della sequenza di conteggio?Java: Converti int [] nella rappresentazione più piccola come intervalli

Esempi:

{1, 2, 3, 4, 5, 9, 13, 14, 15} -> "1-5,9,13-15" 
{4, 6, 8, 10, 11, 12, 15, 17} -> "4,6,8,10-12,15,17" 

Sto cercando un metodo che avrebbe prodotto questi risultati. Questo è quello che ho finora, ma sto molto perplesso a questo punto:

Codice di prova:

import java.util.Arrays; 
public class TestSequencing { 
    public static void main(String[] args) { 
     int[] numbers1 = {1, 2, 3, 4, 5, 9, 13, 14, 15}; 
     String numbers1s = "1-5,9,13-15"; 
     System.out.println(Arrays.toString(numbers1)); 
     System.out.println("Expected:\t" + numbers1s); 
     System.out.println("Produced:\t" + sequenceNums(numbers1) + "\n"); 

     int[] numbers2 = {3, 5, 6, 9, 12}; 
     String numbers2s = "3,5-6,9,12"; 
     System.out.println(Arrays.toString(numbers2)); 
     System.out.println("Expected:\t" + numbers2s); 
     System.out.println("Produced:\t" + sequenceNums(numbers2) + "\n"); 

     int[] numbers3 = {1, 2, 3, 4, 5, 6, 7}; 
     String numbers3s = "1-7"; 
     System.out.println(Arrays.toString(numbers3)); 
     System.out.println("Expected:\t" + numbers3s); 
     System.out.println("Produced:\t" + sequenceNums(numbers3) + "\n"); 
    } 

    public static String sequenceNums(int[] nums) { 
     StringBuilder sb = new StringBuilder(); 
     int rangeStart = nums[0]; 
     int previous = nums[0]; 
     int current; 
     int expected = previous + 1; 

     for (int i = 1 ; i < nums.length ; i++) { 
      current = nums[i]; 
      expected = previous + 1;    
      if (current != expected || i == (nums.length - 1)) { 
       if (current == rangeStart) { 
        sb.append(previous + ","); 
       } else { 
        sb.append(rangeStart + "-" + previous + ","); 
       }     
       rangeStart = current; 
      }    
      previous = current; 
     } 
     if (sb.charAt(sb.length() - 1) == ',') { 
      sb.deleteCharAt(sb.length() - 1); 
     } 
     return sb.toString(); 
    } 
} 

uscita:

[1, 2, 3, 4, 5, 9, 13, 14, 15] 
Expected: 1-5,9,13-15 
Produced: 1-5,9-9,13-14 

[3, 5, 6, 9, 12] 
Expected: 3,5-6,9,12 
Produced: 3-3,5-6,9-9 

[1, 2, 3, 4, 5, 6, 7] 
Expected: 1-7 
Produced: 1-6 
+4

@SotiriosDelimanolis Si prega di essere costruttivi con i vostri commenti. Il mio risultato previsto è chiaramente indicato e l'esempio che ho fornito esemplifica che il mio codice non produce i risultati che sto cercando. –

+0

Ti sto chiedendo perché non fa quello che volevi. Lo hai messo a punto? Cosa hai trovato? –

+0

@SotiriosDelimanolis Suppongo che il problema abbia qualcosa a che fare con la mancanza dell'ultimo numero nell'array. Ho provato idee diverse usando altre strutture di controllo del flusso, ma non ho idea di come possa essere fatto. Il campione che ho fornito è il più vicino che sono venuto a risolvere il mio problema, tuttavia, quindi l'ho postato qui nella speranza di nuove idee da nuove menti. –

risposta

2

Prova questo:

private static void appendRange(StringBuilder sb, int begin, int end) { 
    sb.append(",").append(begin); 
    if (end != begin) 
     sb.append("-").append(end); 
} 

public static String sequenceNums(int[] nums) { 
    StringBuilder sb = new StringBuilder(); 
    if (nums.length == 0) return sb.toString(); 
    int begin = nums[0], end = nums[0]; 
    for (int cur : nums) 
     if (cur - end <= 1) 
      end = cur; 
     else { 
      appendRange(sb, begin, end); 
      begin = end = cur; 
     } 
    appendRange(sb, begin, end); 
    return sb.substring(1); 
} 

@Test 
public void testSequenceNums() { 
    assertEquals("1-5,9,13-15", sequenceNums(new int[] {1, 2, 3, 4, 5, 9, 13, 14, 15})); 
    assertEquals("4,6,8,10-12,15,17", sequenceNums(new int[] {4, 6, 8, 10, 11, 12, 15, 17})); 
    assertEquals("1-7", sequenceNums(new int[] {1, 2, 3, 4, 5, 6, 7})); 
    assertEquals("", sequenceNums(new int[] {})); 
} 
1

nel ciclo for si hanno due problemi :

1) Il secondo if dovrebbe essere if (previous == rangeStart) {

2) Non hai a che fare con l'ultimo numero nel ciclo (dove i == (nums.length - 1)).

Vorrei farlo con il seguente codice:

public static String sequenceNums(int[] nums) { 
    StringBuilder sb = new StringBuilder(); 

    int rangeStart = nums[0]; 
    int previous = nums[0]; 
    int current; 
    int expected = previous + 1; 
    int size = nums.length; 

    for (int i = 1 ; i < size ; i++) { 
     current = nums[i]; 
     expected = previous + 1; 

     if (current != expected) { 
      addRange(sb, rangeStart, previous); 
      rangeStart = current; 
     } 

     previous = current; 
    } 
    addRange(sb, rangeStart, nums[size - 1]); 

    return sb.toString(); 
} 

private void addRange(StringBuilder sb, int from, int to) { 
    if (sb.length() > 0) { 
     sb.append(","); 
    } 
    if (from == to) { 
     sb.append(from); 
    } else { 
     sb.append(from + "-" + to); 
    } 
} 
0

sono stato in grado di risolvere il problema con l'introduzione di un flag booleano e rielaborare il metodo per verificare consecutiva numeri. Se i numeri corrente e successivo sono consecutivi, viene attivato inRangeFlag per l'iterazione successiva. Vedere i commenti del codice qui sotto per ulteriori dettagli:

public static String sequenceNums(int[] nums) { 

    StringBuilder sb = new StringBuilder(); 
    int current; 
    int next; 
    boolean inRangeFlag = false; 

    for (int i = 0; i < nums.length; i++) { 

     current = nums[i]; 

     // TRUE: if element is not last element, because last number is 
     // always appended. 
     if (i < nums.length - 1) { 

      next = nums[i + 1]; 

      // TRUE: if current element and next are consecutive 
      if (next - current == 1) { 

       // If rangeflag is false, the current number is the start 
       // of a range. Append the number with hyphen. 
       if (!inRangeFlag) { 
        sb.append(current + "-"); 
       } 

       // Trigger inRange Flag for next iteration. 
       inRangeFlag = true; 

      } else { 
       sb.append(current + ","); 
       inRangeFlag = false; // Turn flag false because not inRange. 
      } 
     } else { 
      sb.append(current); 
     } 
    } 
    return sb.toString(); 
} 
1

Ecco il codice fisso.

public class TestSequencing { 

    public static void main(String[] args) { 
     int[] numbers1 = {1, 2, 3, 4, 5, 9, 13, 14, 15}; 
     String numbers1s = "1-5,9,13-15"; 
     System.out.println(Arrays.toString(numbers1)); 
     System.out.println("Expected:\t" + numbers1s); 
     System.out.println("Produced:\t" + sequenceNums(numbers1) + "\n"); 

     int[] numbers2 = {3, 5, 6, 9, 12}; 
     String numbers2s = "3,5-6,9,12"; 
     System.out.println(Arrays.toString(numbers2)); 
     System.out.println("Expected:\t" + numbers2s); 
     System.out.println("Produced:\t" + sequenceNums(numbers2) + "\n"); 

     int[] numbers3 = {1, 2, 3, 4, 5, 6, 7}; 
     String numbers3s = "1-7"; 
     System.out.println(Arrays.toString(numbers3)); 
     System.out.println("Expected:\t" + numbers3s); 
     System.out.println("Produced:\t" + sequenceNums(numbers3) + "\n"); 
    } 

    public static String sequenceNums(int[] nums) { 
     StringBuilder sb = new StringBuilder(); 
     int rangeStart = nums[0]; 
     int previous = nums[0]; 
     int current; 
     int expected = previous + 1; 

     for (int i = 1 ; i < nums.length ; i++) { 
      current = nums[i]; 
      expected = previous + 1;    
      if (current != expected || i == (nums.length - 1)) { 
       if (current == rangeStart) { 
        sb.append(previous + ","); 
       } else { 
        if(rangeStart != previous) { 
         if(i == nums.length - 1) 
          sb.append(rangeStart + "-" + current); 
         else 
          sb.append(rangeStart + "-" + previous + ","); 
        } else { 
         if(i == nums.length - 1) 
          sb.append(rangeStart + "," + current); 
         else 
          sb.append(rangeStart + ","); 
        } 
       }     
       rangeStart = current; 
      }    
      previous = current; 
     } 
     if (sb.charAt(sb.length() - 1) == ',') { 
      sb.deleteCharAt(sb.length() - 1); 
     } 
     return sb.toString(); 
    } 

} 

Il problema era che, se la corrente non è uguale valore del campo di partenza, è necessario verificare la presenza di due casi

i) se gamma è stata iniziano con lo stesso valore precedente. In tal caso, non è necessario avere lo stesso numero separato per intervallo (ad esempio: 9-9 non ha senso, solo 9 lo fa). Un altro caso da gestire è la fine dell'array raggiunta. Nel caso in cui venga raggiunta la fine dell'array, dovrebbe essere aggiunta alla fine anche se non rientra in alcun intervallo

ii) altri saggi, l'intervallo inizia e termina con il valore precedente se non viene raggiunta la fine dell'array. Se viene raggiunta la fine dell'array, questo sarebbe il valore finale dell'intervallo

+0

Grazie per la spiegazione!Ho contrassegnato la risposta di @ saka1029 come accettata perché mi piaceva quanto fosse succinto ed efficiente il suo codice, ma la tua risposta era molto più esplicativa ed educativa. –