2009-11-19 22 views
40

Solo encontré una forma de hacerlo al revés: crear una cadena separada por comas de una lista int o matriz, pero no de cómo convertir una entrada como string str = "1,2,3,4,5"; en una matriz o lista de ints.Convertir cadenas de entrada separadas por comas a la matriz int

Aquí está mi aplicación (inspirado por 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; 
       } 
      } 
     } 
    } 

¿Cree que este es un buen enfoque o hay un más fácil, tal vez incluso construido en el camino?

EDIT: Lo sentimos por cualquier confusión, pero el método tiene que manejar la entrada no válida como "1,2,,,3" o "###, 5," etc. saltándose ella.

+0

Usted está complicando innecesariamente su código al no utilizar 'foreach'. La publicación desde la que estás copiando está resolviendo un problema completamente diferente. – SLaks

Respuesta

50

se debe utilizar un bucle foreach, así:

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; 
    } 
} 

Nota que al igual que su puesto original, esto no hará caso de números que no se pudo analizar.

Si desea lanzar una excepción si un número no se pudo analizar, que puede hacer que sea mucho más simple uso de LINQ:

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

¡Gracias, buenísimo! Mucho más fácil que mi enfoque. Sin embargo, hay un {missing after the foreach. – Max

+0

Solucionado; Gracias. – SLaks

2

Esto es para longs, pero puedes modificarlo fácilmente para trabajar con ints.

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

Esto arrojará números irreprochables; parece que quiere omitirlos. – SLaks

+0

Esto no hace lo mismo. Su versión maneja graciosamente números enteros saltándolos. – mquander

+0

Buen punto, pero estaba yendo por el ejemplo de entrada que proporcionó: cadena str = "1,2,3,4,5" – dcp

1

no veo por qué sacar el encuestador le ofrece de forma explícita cualquier ventaja sobre usar un foreach. Tampoco es necesario llamar al AsEnumerable en chunks.

0

Creo que es lo suficientemente bueno. Está claro, es flojo, así que será rápido (excepto tal vez el primer caso cuando se divide la cadena).

+0

No estoy de acuerdo; en realidad, debería usar 'foreach', lo que lo haría mucho más claro. Además, es innecesariamente detallado. – SLaks

+0

Dije, lo suficientemente bueno, no perfecto. No me lastima los ojos, solo déjalo como está y busca otra cosa ... –

52

Si no quieren tener el comportamiento actual de gestión de errores, que es muy fácil:

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

De lo contrario, que haría uso de un método de ayuda adicional (as seen this morning!):

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

y:

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

o si no desea utilizar la conversión de grupo método:

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

o en forma de expresión de consulta:

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

Para un chico java/C#, tus respuestas siempre me parecen muy funcionales: =) – Peter

+0

Cuando se trata de LINQ, eso es no del todo sorprendente :) –

+0

¿Por qué no quieres usar la conversión del grupo de métodos? – SLaks

4

Esto se ha hecho antes. .Net tiene una función ConvertAll incorporada para convertir una matriz de un tipo a una matriz de otro tipo.Esto se puede combinar con la división para separar la cadena a una matriz de cadenas

función Ejemplo:

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

Taken from here

6

--EDIT-- Parece que tomé su pregunta en dirección demasiado literalmente - que estaba pidiendo una matriz de enteros en lugar de una lista --edit ENDS--

Sin embargo, otro método de ayuda ...

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(); 
} 

código rápido de prueba para ella, también ...

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

Sin utilizar una función lambda y de entradas válidas solamente, creo que es más clara para hacer esto:

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

encontré que no necesitaba esta parte '' –

0

me gustan un simple solución que funcionó para mí.

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

Cuestiones relacionadas