Андрей Котов Asked:2022-01-29 16:37:33 +0000 UTC2022-01-29 16:37:33 +0000 UTC 2022-01-29 16:37:33 +0000 UTC 在分隔符 C# 处拆分字符串 772 我有一个包含 2 列数字的 csv 文件 3,"5,19615242270663" "4,5",8 6,"11,1803398874989" 如何从此列表中获取二维数字数组? c# 2 个回答 Voted VladD 2022-01-29T17:36:44Z2022-01-29T17:36:44Z 如果你需要实现这个进行学习或培训:我不会给出现成的代码以便你自己学习,我只会给出提示。 看,你需要写一个真正的解析器。您可以在引号中使用逗号,因此“天真”地解析string.Split将不起作用。做这个。 一次扫描一个字符的字符串。获取一个标志,指示您当前是否在引号内。 如果在引号之外遇到逗号,则上一个条目已结束。如果在这种模式下遇到换行符(CR + LF),那么 CSV 行就结束了。如果在录制开始时遇到引号,请切换到“引用”模式。不在条目开头的引号是格式违规。 如果您在引号内看到逗号,这不是条目的结尾,请继续扫描。如果遇到引号,请退出引号模式,除非下一个字符是引号。(如果下一个字符是引号,那么这两个引号一起在条目值中形成一个引号。)如果遇到换行符,它不会结束该行,而是包含在条目中。退出报价模式后,必须有记录的结尾,即逗号,或者CR + LF,或者文本的结尾,否则CSV无效。 获得所有条目后,确保每一行包含相同数量的条目(这也可以在解析文本时完成)。第一行可以包含(或不包含)列名,所有后续行都包含值。 现在您可以尝试将所有记录转换为double使用double.TryParse. 如果有的话,这里是一个带有格式描述的 RFC:https ://www.rfc-editor.org/rfc/rfc4180 。 如果这不是一项教育任务,那么请使用普通的 CSV 解析器,不要制造自行车。 Best Answer aepot 2022-01-29T18:50:05Z2022-01-29T18:50:05Z 您需要的“天真”实现,能够从问题中消化您的示例,可能看起来像这样。 static void Main(string[] args) { string text = @"3,""5,19615242270663"" ""4,5"",8 6,""11,1803398874989"" "; try { double[,] numbers = CsvToDoubleArray(text); for (int i = 0; i < numbers.GetLength(0); i++) Console.WriteLine(string.Join(" ", Enumerable.Range(0, numbers.GetLength(1)).Select(j => numbers[i, j]))); } catch (Exception ex) { Console.WriteLine(ex.Message); } } static double[,] CsvToDoubleArray(string text) { string[] lines = text.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries); double[,] result = null; for (int i = 0; i < lines.Length; i++) { string line = lines[i]; List<string> tokens = new List<string>(); StringBuilder token = new StringBuilder(); bool mode = false; for (int j = 0; j < line.Length; j++) { switch (line[j]) { case '\\': j++; if (j < line.Length) token.Append(line[j]); break; case '"': mode = !mode; break; case ',': if (mode) token.Append(line[j]); else { tokens.Add(token.ToString()); token.Clear(); } break; default: token.Append(line[j]); break; } } tokens.Add(token.ToString()); if (result == null) result = new double[lines.Length, tokens.Count]; for (int j = 0; j < result.GetLength(1); j++) { result[i, j] = double.Parse(tokens[j]); } } return result; } 此代码可能需要在不同方向上进行大量工作,从处理 CSV 中的不同错误到支持不同的分隔符,以及@VladD 的相邻答案中提到的其他要点。这个例子的重点是它适用于您提供的数据。我不知道它将如何与其他数据一起使用。 控制台输出 3 5,19615242270663 4,5 8 6 11,1803398874989
如果你需要实现这个进行学习或培训:我不会给出现成的代码以便你自己学习,我只会给出提示。
看,你需要写一个真正的解析器。您可以在引号中使用逗号,因此“天真”地解析
string.Split将不起作用。做这个。一次扫描一个字符的字符串。获取一个标志,指示您当前是否在引号内。
如果在引号之外遇到逗号,则上一个条目已结束。如果在这种模式下遇到换行符(CR + LF),那么 CSV 行就结束了。如果在录制开始时遇到引号,请切换到“引用”模式。不在条目开头的引号是格式违规。
如果您在引号内看到逗号,这不是条目的结尾,请继续扫描。如果遇到引号,请退出引号模式,除非下一个字符是引号。(如果下一个字符是引号,那么这两个引号一起在条目值中形成一个引号。)如果遇到换行符,它不会结束该行,而是包含在条目中。退出报价模式后,必须有记录的结尾,即逗号,或者CR + LF,或者文本的结尾,否则CSV无效。
获得所有条目后,确保每一行包含相同数量的条目(这也可以在解析文本时完成)。第一行可以包含(或不包含)列名,所有后续行都包含值。
现在您可以尝试将所有记录转换为
double使用double.TryParse.如果有的话,这里是一个带有格式描述的 RFC:https ://www.rfc-editor.org/rfc/rfc4180 。
如果这不是一项教育任务,那么请使用普通的 CSV 解析器,不要制造自行车。
您需要的“天真”实现,能够从问题中消化您的示例,可能看起来像这样。
此代码可能需要在不同方向上进行大量工作,从处理 CSV 中的不同错误到支持不同的分隔符,以及@VladD 的相邻答案中提到的其他要点。这个例子的重点是它适用于您提供的数据。我不知道它将如何与其他数据一起使用。
控制台输出