2013-04-16 20 views
5

Quello che voglio fare è dividere l'ennesima occorrenza di una stringa (in questo caso è "\ t"). Questo è il codice che sto usando attualmente e si divide su ogni occorrenza di "\ t".Come dividere una stringa all'ennesima occorrenza?

string[] items = input.Split(new char[] {'\t'}, StringSplitOptions.RemoveEmptyEntries); 

Se l'ingresso = "uno \ TTWO \ Tthree \ tfour", il mio codice restituisce l'array di:

  • uno
  • due
  • tre
  • quattro

Ma diciamo che voglio dividerlo su ogni "\ t" dopo il secondo "\ t". Quindi, dovrebbe restituire:

  • uno due
  • tre
  • quattro
+4

'\ t' non è un ritorno a capo; è una scheda. Intendevi dire "newline"? –

+3

la tua domanda non è chiara editala – gasroot

+0

Oh, giusto. Intendevo tab allora. Ma non importa. Dovrebbe essere lo stesso metodo per dividere qualsiasi stringa all'ennesima occorrenza e come posso farlo? –

risposta

15

Non c'è niente di costruito nel

È possibile utilizzare l'esistente Split, utilizzare Take e Skip con. string.Join per ricostruire le parti che avevate in origine.

string[] items = input.Split(new char[] {'\t'}, 
          StringSplitOptions.RemoveEmptyEntries); 
string firstPart = string.Join("\t", items.Take(nthOccurrence)); 
string secondPart = string.Join("\t", items.Skip(nthOccurrence)) 

string[] everythingSplitAfterNthOccurence = items.Skip(nthOccurrence).ToArray(); 

Un'alternativa è quella di iterare su tutti i caratteri della stringa, trovare l'indice del verificarsi ennesima e sottostringa prima e dopo di esso (o trovare l'indice successivo dopo l'ennesima, sottostringa su quel ecc ... ecc ... ecc ...).

+1

Questo è molto meglio del mio Non ero a conoscenza delle opzioni 'Take' e' Skip'. Ottima risposta ... – MoonKnight

+0

L'OP ha modificato la sua domanda, quindi sembra che voglia dividere ogni occorrenza * dopo * l'ennesima, quindi il requisito è cambiato. –

+0

@MatthewWatson - Beh, abbastanza facile. Il 'Skip' lo farà. – Oded

1

È probabile che sarà necessario suddividere e ricombinare. Qualcosa di simile

int tabIndexToRemove = 3; 
string str = "My\tstring\twith\tloads\tof\ttabs"; 
string[] strArr = str.Split('\t'); 
int numOfTabs = strArr.Length - 1; 
if (tabIndexToRemove > numOfTabs) 
    throw new IndexOutOfRangeException(); 
str = String.Empty; 
for (int i = 0; i < strArr.Length; i++) 
    str += i == tabIndexToRemove - 1 ? 
     strArr[i] : String.Format("{0}\t", strArr[i]); 

Risultato:

mia stringa withloads di schede

Spero che questo aiuta.

0
// Return a substring of str upto but not including 
// the nth occurence of substr 
function getNth(str, substr, n) { 
    var idx; 
    var i = 0; 
    var newstr = ''; 
    do { 
    idx = s.indexOf(c); 
    newstr += str.substring(0, idx); 
    str = str.substring(idx+1); 
    } while (++i < n && (newstr += substr)) 
    return newstr; 
} 
4

[EDIT] Dopo aver riletto l'OP modificato, mi rendo conto che questo non fa ciò che viene ora richiesto. Questo si dividerà su ogni ennesimo obiettivo; l'OP vuole dividersi su ogni obiettivo DOPO l'ennesimo.

Lo lascerò qui per i posteri comunque.


Se si sta utilizzando il MoreLinq extensions si potrebbe approfittare del suo metodo Batch.

Il tuo codice sarebbe quindi simile a questa:

string text = "1\t2\t3\t4\t5\t6\t7\t8\t9\t10\t11\t12\t13\t14\t15\t16\t17"; 

var splits = text.Split('\t').Batch(5); 

foreach (var split in splits) 
    Console.WriteLine(string.Join("", split)); 

probabilmente sarei basta usare l'implementazione di Oded, ma ho pensato che avrei posto questo per un approccio alternativo.

L'attuazione di Batch() assomiglia a questo:

public static class EnumerableExt 
{ 
    public static IEnumerable<IEnumerable<TSource>> Batch<TSource>(this IEnumerable<TSource> source, int size) 
    { 
     TSource[] bucket = null; 
     var count = 0; 

     foreach (var item in source) 
     { 
      if (bucket == null) 
       bucket = new TSource[size]; 

      bucket[count++] = item; 

      if (count != size) 
       continue; 

      yield return bucket; 

      bucket = null; 
      count = 0; 
     } 

     if (bucket != null && count > 0) 
      yield return bucket.Take(count); 
    } 
} 
+1

+1 Il lotto è bello! – MoonKnight

Problemi correlati