2009-11-19 17 views
40

Ho trovato solo un modo per farlo in senso inverso: creare una stringa separata da una lista int o array, ma non su come convertire input come string str = "1,2,3,4,5"; in una matrice o lista di ints.Converta una stringa separata da virgola a int array

Qui è la mia realizzazione (ispirati da this post by Eric Lippert):

public static IEnumerable<int> StringToIntList(string str) 
    { 
     if (String.IsNullOrEmpty(str)) 
     { 
      yield break; 
     } 

     var chunks = str.Split(',').AsEnumerable(); 

     using (var rator = chunks.GetEnumerator()) 
     { 
      while (rator.MoveNext()) 
      { 
       int i = 0; 

       if (Int32.TryParse(rator.Current, out i)) 
       { 
        yield return i; 
       } 
       else 
       { 
        continue; 
       } 
      } 
     } 
    } 

Pensi che questo è un buon approccio o c'è un più facile, forse anche costruito in modo?

EDIT: Purtroppo per qualsiasi confusione, ma il metodo deve gestire input non valido come "1,2,,,3" o "###, 5," ecc saltando esso.

+0

Stai inutilmente complicare il codice non usando 'foreach'. Il post di cui stai copiando sta risolvendo un problema completamente diverso. – SLaks

risposta

50

è necessario utilizzare un ciclo foreach, in questo modo:

public static IEnumerable<int> StringToIntList(string str) { 
    if (String.IsNullOrEmpty(str)) 
     yield break; 

    foreach(var s in str.Split(',')) { 
     int num; 
     if (int.TryParse(s, out num)) 
      yield return num; 
    } 
} 

notare che, come il tuo post originale, questo ignorerà numeri che non possono essere letti.

Se si desidera generare un'eccezione se un numero non poteva essere analizzato, si può fare molto più semplicemente utilizzando LINQ:

return (str ?? "").Split(',').Select<string, int>(int.Parse); 
+1

Grazie, bello! Molto più facile del mio approccio. C'è un {mancante dopo il foreach però. – Max

+0

Riparato; Grazie. – SLaks

2

Questo è per lunghi, ma è possibile modificarlo facilmente per lavorare con ints.

private static long[] ConvertStringArrayToLongArray(string str) 
{ 
    return str.Split(",".ToCharArray()).Select(x => long.Parse(x.ToString())).ToArray(); 
} 
+0

Questo getterà su numeri non ripetibili; sembra voler saltarli. – SLaks

+0

Questo non fa la stessa cosa. La sua versione gestisce i non interi con grazia saltandoli. – mquander

+0

Un buon punto, ma stavo seguendo l'esempio di input che ha fornito: string str = "1,2,3,4,5" – dcp

1

non vedo il motivo per cui tirando fuori l'enumeratore si offre in modo esplicito qualsiasi vantaggio rispetto all'utilizzo di un foreach. Non è inoltre necessario chiamare lo AsEnumerable allo chunks.

0

Penso che sia abbastanza buono. È chiaro, è pigro, quindi sarà veloce (tranne forse il primo caso quando dividi la stringa).

+0

Non sono d'accordo; _really_ dovrebbe usare 'foreach', che renderebbe molto più chiaro. Inoltre, è inutilmente prolisso. – SLaks

+0

Ho detto, abbastanza buono, non perfetto. Non mi fa male agli occhi, basta lasciarlo così com'è e andare per un'altra cosa .... –

52

Se non si desidera avere il comportamento attuale gestione degli errori, è davvero facile:

return text.Split(',').Select(x => int.Parse(x)); 

In caso contrario, mi piacerebbe utilizzare un metodo di supporto in più (as seen this morning!):

public static int? TryParseInt32(string text) 
{ 
    int value; 
    return int.TryParse(text, out value) ? value : (int?) null; 
} 

e:

return text.Split(',').Select<string, int?>(TryParseInt32) 
         .Where(x => x.HasValue) 
         .Select(x => x.Value); 

o se non si desidera utilizzare il metodo di conversione di gruppo:

return text.Split(',').Select(t => t.TryParseInt32(t) 
         .Where(x => x.HasValue) 
         .Select(x => x.Value); 

o in forma di espressione di query:

return from t in text.Split(',') 
     select TryParseInt32(t) into x 
     where x.HasValue 
     select x.Value; 
+0

Per un ragazzo java/C#, le tue risposte mi sembrano sempre molto funzionali: =) – Peter

+0

Quando si tratta di LINQ, quello è non del tutto sorprendente :) –

+0

Perché non vuoi usare la conversione del gruppo metodo? – SLaks

4

questo è stato chiesto prima. .Net ha una funzione ConvertAll incorporata per la conversione tra un array di un tipo in un array di un altro tipo.È possibile combinare questo con Spalato per separare la stringa in un array di stringhe

funzione Esempio:

static int[] ToIntArray(this string value, char separator) 
{ 
    return Array.ConvertAll(value.Split(separator), s=>int.Parse(s)); 
} 

Taken from here

6

--EDIT-- Sembra che ho preso la sua domanda voce troppo alla lettera - stava chiedendo per una serie di interi piuttosto che un elenco --edit ENDS--

ancora un altro metodo di supporto ...

private static int[] StringToIntArray(string myNumbers) 
{ 
    List<int> myIntegers = new List<int>(); 
    Array.ForEach(myNumbers.Split(",".ToCharArray()), s => 
    { 
     int currentInt; 
     if (Int32.TryParse(s, out currentInt)) 
      myIntegers.Add(currentInt); 
    }); 
    return myIntegers.ToArray(); 
} 

codice di test rapido per questo, troppo ...

static void Main(string[] args) 
{ 
    string myNumbers = "1,2,3,4,5"; 
    int[] myArray = StringToIntArray(myNumbers); 
    Console.WriteLine(myArray.Sum().ToString()); // sum is 15. 

    myNumbers = "1,2,3,4,5,6,bad"; 
    myArray = StringToIntArray(myNumbers); 
    Console.WriteLine(myArray.Sum().ToString()); // sum is 21 

    Console.ReadLine(); 
} 
22

Senza l'utilizzo di una funzione lambda e per gli ingressi validi solo, penso che sia più chiaro per fare questo:

Array.ConvertAll<string, int>(value.Split(','), Convert.ToInt32); 
+1

ho trovato che non avevo bisogno di questa parte '' –

0

ho un semplice appassionato soluzione che ha funzionato per me.

String.Join(",",str.Split(','));

Problemi correlati