2013-01-23 10 views
5

Ho stringa seguente:Come sottostringa tra due separatori in una posizione arbitraria

string source = "Test/Company/Business/Department/Logs.tvs/v1"; 

Il carattere / è il separatore tra i vari elementi nella stringa. Ho bisogno di prendere gli ultimi due elementi della stringa. Ho il seguente codice per questo scopo. Funziona bene C'è un codice più veloce/più semplice per questo?

CODICE

static void Main() 
    { 
     string component = String.Empty; 
     string version = String.Empty; 
     string source = "Test/Company/Business/Department/Logs.tvs/v1"; 
     if (!String.IsNullOrEmpty(source)) 
     { 
      String[] partsOfSource = source.Split('/'); 
      if (partsOfSource != null) 
      { 
       if (partsOfSource.Length > 2) 
       { 
        component = partsOfSource[partsOfSource.Length - 2]; 
       } 

       if (partsOfSource.Length > 1) 
       { 
        version = partsOfSource[partsOfSource.Length - 1]; 
       } 
      } 
     } 

     Console.WriteLine(component); 
     Console.WriteLine(version); 
     Console.Read(); 
    } 

risposta

4

Perché nessuna espressione regolare? Questo è abbastanza semplice:

.*/(?<component>.*)/(?<version>.*)$ 

È anche possibile etichettare i gruppi in modo per la vostra partita tutto quello che dovete fare è:

component = myMatch.Groups["component"]; 
version = myMatch.Groups["version"]; 
+1

E 'un peccato che si può' t fare in modo che il motore regex corrisponda "di destra" in casi come questo. – Rawling

+1

@Rawling: concordato. Immagino che potresti invertire prima la stringa, ma probabilmente è anche meno efficiente. In realtà, mi chiedo se non sia possibile per un motore RegEx incorporare questo tipo di ottimizzazione quando un'espressione ha un '$' ma non '^'. –

+2

... OK, oggi ho imparato che puoi fare qualcosa come 'Regex.Match (source," /(.*?)/(.*?)$ ", RegexOptions.RightToLeft)', o anche senza '$' in questo caso. – Rawling

2

il codice sia per lo più bene. Un paio di punti da notare:

  1. String.Split() non restituirà mai null, quindi non è necessario il controllo Null su di esso.
  2. Se la stringa source contiene meno di due caratteri /, come gestirli? (Il post originale è stato aggiornato per risolvere questo problema)
  3. Vuoi veramente generare stringhe vuote solo se la stringa di origine è nullo o vuoto (o non valido)? Se hai delle aspettative specifiche sulla natura dell'input, potresti considerare di fallire velocemente quando quelle aspettative non vengono soddisfatte.
2

Il tuo approccio è quello più adatto visto che siete alla ricerca di sottostringhe a un indice particolare. Un'espressione LINQ per fare lo stesso in questo caso probabilmente non migliorerà il codice o la sua leggibilità.

Per riferimento, ci sono alcune ottime informazioni da Microsoft here su come lavorare con stringhe e LINQ. In particolare vedere l'articolo here che copre alcuni esempi con LINQ e RegEx.

MODIFICA: +1 Per il gruppo denominato Matt all'interno dell'approccio RegEx ... questa è la soluzione più bella che abbia mai visto.

3

Il seguente dovrebbe essere più veloce, in quanto esegue la scansione solo la quantità della stringa come ha bisogno di trovare due / e non si preoccupa frazionamento l'intera stringa:

string component = ""; 
string version = ""; 
string source = "Test/Company/Business/Department/Logs.tvs/v1"; 
int last = source.LastIndexOf('/'); 
if (last != -1) 
{ 
    int penultimate = source.LastIndexOf('/', last - 1); 
    version = source.Substring(last + 1); 
    component = source.Substring(penultimate + 1, last - penultimate - 1); 
} 

Detto , come con tutte le domande sulle prestazioni: profilo! Prova i due side-by-side con una grande lista di input di vita reale e vedi quale è il più veloce.

(Inoltre, questo lascerà stringhe vuote, piuttosto che un'eccezione se non v'è alcuna barra in ingresso ... ma buttare se source è null, pigro di me.)

+0

Sembra un'ottimizzazione prematura. È altamente improbabile che la suddivisione di questa stringa costituisca un collo di bottiglia per le prestazioni. – StriplingWarrior

+0

Ancora, quando OP ha richiesto un codice più veloce/più semplice ... – Rawling

1

Si potrebbe provare qualcosa di simile questo ma dubito che sarebbe molto più veloce. Potresti fare alcune misurazioni con System.Diagnostics.StopWatch per vedere se ne senti il ​​bisogno.

string source = "Test/Company/Business/Department/Logs.tvs/v1"; 

int index1 = source.LastIndexOf('/'); 
string last = source.Substring(index1 + 1); 

string substring = source.Substring(0, index1); 
int index2 = substring.LastIndexOf('/'); 
string secondLast = substring.Substring(index2 + 1); 
1

vorrei provare

 string source = "Test/Company/Business/Department/Logs.tvs/v1"; 

     var components = source.Split('/').Reverse().Take(2); 

     String last = string.Empty; 

     var enumerable = components as string[] ?? components.ToArray(); 
     if (enumerable.Count() == 2) 
      last = enumerable.FirstOrDefault(); 
     var secondLast = enumerable.LastOrDefault(); 

Spero che questo vi aiuterà

+0

Interessante ... Grazie – Lijo

+1

@Lijo ha modificato la mia risposta con alcuni refactoring da R # e ha aggiunto il supporto per components.Count <2 (Spero che questo aiuti) – jbl

-1

è possibile recuperare le ultime due parole che utilizzano il processo come di seguito:

string source = "Test/Company/Business/Department/Logs.tvs/v1"; 

String[] partsOfSource = source.Split('/'); 
if(partsOfSourch.length>2) 
for(int i=partsOfSourch.length-2;i<=partsOfSource.length-1;i++) 
console.writeline(partsOfSource[i]); 
Problemi correlati