como sugiere el título, estoy buscando orientación sobre cómo convertir una cadena (csvData) en una matriz de cadenas 2D dividiéndola dos veces con ';'
y ','
respectivamente. Actualmente estoy en la etapa en la que puedo dividirlo una vez en filas y convertirlo en una matriz, pero no puedo entender cómo crear una matriz 2D donde las columnas divididas por ','
también están separadas.
string[] Sep = csvData.Split(';').Select(csvData => csvData.Replace(" ","")).Where(csvData => !string.IsNullOrEmpty(csvData)).ToArray();
He probado varias cosas como:
string[,] Sep = csvData.Split(';',',').Select(csvData => csvData.Replace(" ","")).Where(csvData => !string.IsNullOrEmpty(csvData)).ToArray();
pensando ingenuamente que C# entendería lo que traté de lograr, pero como estoy aquí, es obvio que obtuve el error de que "no se puede convertir implícitamente el tipo string[]
en string [*,*]
"
Tenga en cuenta que no he codificado por un tiempo, por lo que si mi forma de pensar es completamente incorrecta y no entiende lo que estoy tratando de transmitir con esta pregunta, me disculpo de antemano. ¡Gracias!
En un lenguaje fuertemente tipado como C#, el compilador no hace suposiciones sobre lo que pretende hacer con sus datos. Debe hacer que su intención sea explícita a través de su código. Algo como esto debería funcionar:
string csvData = "A,B;C,D"; string[][] sep = csvData.Split(';') // Returns string[] {"A,B","C,D"} .Select(str => str.Split(',')) // Returns IEnumerable<string[]> {{"A","B"},{"C","D"}} .ToArray(); // Returns string[][] {{"A","B"},{"C","D"}}
¿Las filas están separadas por punto y coma, las columnas por coma?
Dividir por ';' te da una matriz de filas. Dividir una fila por ',' le da una matriz de valores.
Si sus datos tienen un esquema consistente, como en cada csv que procesa tiene las mismas columnas, puede definir una clase para representar la entidad para facilitar el manejo de los datos.
Digamos que son los datos del cliente:
John,Smith,8675309,johnsmith@gmail.com;
Podrías hacer una clase con esas propiedades:
public class Customer { public string FirstName { get; set; } public string LastName { get; set; } public string Phone { get; set; } public string Email { get; set; } }
Luego:
var rows = csvdata.Split(';'); List<Customer> customers = new(); foreach(var row in rows) { var customer = row.Split(','); customers.Add(new() { FirstName = row[0], LastName = row[1], Phone = row[2], Email = row[3] }); }
Ahora tiene una lista de clientes para hacer lo que sea que haga con los clientes.
Aquí hay una respuesta para presentar algunas ideas alternativas y cosas que puede hacer con C #, más con fines educativos/académicos que cualquier otra cosa. En estos días, para consumir un CSV, usaríamos una biblioteca CSV
Si sus datos definitivamente se forman regularmente, puede salirse con la suya con solo una división. El siguiente código se divide en cualquiera de los caracteres para formar una matriz larga. Entonces es lógico que cada 4 elementos sea un nuevo cliente, los datos del cliente están dados por n+0, n+1, n+2 y n+3. Como sabemos cuántos elementos de datos consumiremos, dividirlo por 4 nos da la cantidad de clientes para que podamos predimensionar nuestra matriz 2D
var bits = data.Split(';',','); var twoD = new string[bits.Length/4,4]; for(int x = 0; x < bits.Length; x+=4){ twoD[x/4,0] = bits[x+0]; twoD[x/4,1] = bits[x+1]; twoD[x/4,2] = bits[x+2]; twoD[x/4,3] = bits[x+3]; }
Sin embargo, no creo que usaría matrices 2D, y elogio la otra respuesta que aconseja crear una clase para contener los datos relacionados; puedes usar esta misma tecnica
var custs = new List<Customer>(); for(int x = 0; x < bits.Length;){ custs.Add(new() { FirstName = bits[x++], LastName = bits[x++], Phone = bits[x++], Email = bits[x++] }); }
Aquí no estamos incrementando x en el encabezado del ciclo; cada vez que se asigna un bit de información, x
aumenta 1 en el cuerpo del bucle. Podríamos haber mantenido el mismo enfoque que antes, saltándolo en 4, simplemente demostrando otro enfoque que se presta bien aquí.
Mencioné que en estos días probablemente no leeríamos un csv manualmente y nos dividiríamos. ¿Qué sucede si los datos contienen una coma o un punto y coma? Destruye la estructura del archivo.
Hay un montón de bibliotecas que leen archivos CSV, CsvHelper es popular y lo usaría como:
using var reader = new StreamReader("path\\to\\file.csv"); using var csv = new CsvReader(reader, CultureInfo.InvariantCulture) var custs = csv.GetRecords<Customer>().ToList(); ...
Su archivo tendría una línea de encabezado con nombres de columna que coincidan con los nombres de sus propiedades en C#. Si no es así, puede usar atributos en las propiedades para decirle a CsvH qué columna debe asignarse a qué propiedad: https://joshclose.github.io/CsvHelper/getting-started/
Esta es la forma más sencilla que conozco de producir una matriz 2D dividiendo una cadena.
string csvData = "A,B,C;D,E,F,G"; var temporary = csvData .Split(';') .SelectMany((xs, i) => xs.Split(',').Select((x, j) => new { x, i, j })) .ToArray(); int max_i = temporary.Max(x => xi); int max_j = temporary.Max(x => xj); string[,] array = new string[max_i + 1, max_j + 1]; foreach (var t in temporary) { array[ti, tj] = tx; }
Elegí deliberadamente csvData
para que faltara un valor.
temporary
es esto:
Y la array
final es esta: