删除特定单词的二维数组

3

我有一个小问题。我有一个包含 "NaN" 值和双精度数值(例如0.6034)的 .csv 文件,我想要将 CSV 中的双精度数值读取到一个数组[y][x] 中。

目前,我已经读取了整个 .csv 文件,但是我无法成功删除所有 "NaN" 值。(它应该通过解析 CSV 并将数字添加到数组[y][x] 中,留下所有的 "NaN")

我的当前代码:

 var rows = File.ReadAllLines(filepath).Select(l => l.Split(';').ToArray()).ToArray(); //reads WHOLE .CSV to array[][]


        int max_Rows = 0, j, rank;
        int max_Col = 0;
        foreach (Array anArray in rows)
        {
            rank = anArray.Rank;
            if (rank > 1)
            {
                 // show the lengths of each dimension
                for (j = 0; j < rank; j++)
                {

                }
            }
            else
            {

            }
            // show the total length of the entire array or all dimensions

            max_Col = anArray.Length; //displays columns
            max_Rows++;  //displays rows
        }

我尝试了搜索,但没有找到有用的内容。我知道这可能很简单,但我刚开始接触C#。

.CSV文件和期望的结果:

NaN;NaN;NaN;NaN
NaN;1;5;NaN
NaN;2;6;NaN
NaN;3;7;NaN
NaN;4;8;NaN
NaN;NaN;NaN;NaN

这是一个样例.csv文件。抱歉我之前没有说清楚!每一行都包含一个NaN值,我希望它显示为:

1;5
2;6
3;7
4;8

这只是一个样本.csv文件,真正的csv文件有大约60,000个值...我需要使用[y][x]获取输入,例如[0][0]应该显示“1”,[2][1]应该显示“7”等等。
再次感谢您的所有帮助!

顺便说一句,我绝对不敢自己编写CSV解析器。我认为这种情况太多了(例如:https://dev59.com/E2w15IYBdhLWcg3wmM19#6516246)。 - Uwe Keim
@Uwe Keim:我同意你的观点,在普遍情况下,CSV可能足够复杂;然而当CSV源是已知的(例如,我的例程从RDMBS导出数据供未来分析使用),或者在单次使用软件的情况下(我只想删除不完整的行并在提供的CSV上执行线性回归),我会更加宽容。 - Dmitry Bychenko
2个回答

6
你可以在数组中筛选出你需要的分隔值。
我稍微修改了你的代码。
 File.ReadAllLines(filepath).Select(l => l.Split(';').ToArray().Where(y => y != "NaN").ToArray()).ToArray();

这看起来不错,但在使用时,当我通过显示数组的1.值->MessageBox.Show(Convert.ToString(rows[0][0])) 来检查结果时,出现了一些奇怪的“错误”。它显示“false”,而对于 MessageBox.Show(Convert.ToString(rows[10][10])) 则显示“true”,而不是数字。我在这里做错了什么?您的解决方案应该有效,我认为它非常简单=)谢谢 - christian890
你不需要使用 ReadAllLines(过早的数据实例化),使用 ReadLines 会更好一些。 - Dmitry Bychenko
1
@christian890 我稍微修改了一下代码。因为我没有使用任何数据进行测试,所以出现了错误,我使用了 select 而不是 where - scartag
1
@christian890 我尝试了你的值,它对我有效...虽然在这些值中我得到了很多特殊字符..可能是因为我从页面上复制的原因吧。 - scartag
1
@christian890,我在想你是否可以手动创建一个新的CSV文件来测试代码,然后检查实际的CSV文件是否具有所需的正确换行符。我相信文件和其内容肯定存在问题。 - scartag
显示剩余8条评论

1
如果您想删除包含NAN的所有行(CSV的典型任务-清理所有不完整的行),例如:
  123.0; 456; 789
    2.1; NAN;  35     <- this line should be removed (has NaN value)
     -5;   3;  18

你可以像这样实现它。
  double[][] data = File
    .ReadLines(filepath)
    .Select(line => line.Split(new char[] {';', '\t'},
                               StringSplitOptions.RemoveEmptyEntries))
    .Where(items => items  // Filter first...
       .All(item => !string.Equals("NAN", item, StringComparison.OrdinalIgnoreCase)))
    .Select(items => items
       .Select(item => double.Parse(item, CultureInfo.InvariantCulture))
       .ToArray()) // ... materialize at the very end
    .ToArray();

使用string.Join来显示行:
 string report = string.Join(Environment.NewLine, data
   .Select(line => string.Join(";", line)));

 Console.Write(report);

编辑:实际问题是仅从CSV中获取第二列和第三列的完整内容:

NaN;NaN;NaN;NaN
NaN;1;5;NaN
NaN;2;6;NaN
NaN;3;7;NaN
NaN;4;8;NaN
NaN;NaN;NaN;NaN

期望的结果是:
[[1, 5], [2, 6], [3, 7], [4, 8]]

implmentation:

double[][] data = File
  .ReadLines(filepath)
  .Select(line => line
     .Split(new char[] {';'},
            StringSplitOptions.RemoveEmptyEntries)
     .Skip(1) 
     .Take(2)
     .Where(item => !string.Equals("NAN", item, StringComparison.OrdinalIgnoreCase))
     .ToArray())
  .Where(items => items.Length == 2)
  .Select(items => items
    .Select(item => double.Parse(item, CultureInfo.InvariantCulture))
    .ToArray())
  .ToArray();

测试

// 1
Console.Write(data[0][0]);
// 5
Console.Write(data[0][1]);
// 2
Console.Write(data[1][0]);

一次性获取所有值:

string report = string.Join(Environment.NewLine, data
   .Select(line => string.Join(";", line)));

Console.Write(report);

结果:
1;5
2;6
3;7
4;8 

编辑2:如果您只想提取非NaN值(请注意,初始CSV结构将被破坏):
1;2;3              1;2;3
NAN;4;5            4;5   <- please, notice that the structure is lost
6;NAN;7        ->  6;7
8;9;NAN;           8;9
NAN;10;NAN         10
NAN;NAN;11         11 

那么

double[][] data = File
  .ReadLines(filepath)
  .Select(line => line
     .Split(new char[] {';'},
            StringSplitOptions.RemoveEmptyEntries)
     .Where(item => !string.Equals("NAN", item, StringComparison.OrdinalIgnoreCase)))
  .Where(items => items.Any()) 
  .Select(items => items
    .Select(item => double.Parse(item, CultureInfo.InvariantCulture))
    .ToArray())
  .ToArray();

1
@christian890:对于打字错误我很抱歉:string.Equals("NAN", item... 我们应该比较 NANitem - Dmitry Bychenko
1
@christian890:我明白了;如果你想提取第二和第三行的完整行,则请查看我的编辑;由于“data”是一个不规则数组,因此您可以按照所需的方式获取所需的项目:“data[x][y]”,例如,data[0][0]应返回1 - Dmitry Bychenko
1
@christian890:错误的原因是CSV中的某个值既不是NaN也不是有效的double值,例如“bla-bla-bla”。请提供实际的CSV文件,谢谢。 - Dmitry Bychenko
1
@christian890:你不仅需要删除 NaN,还需要删除空值 - .Split(new char[] {';'}, StringSplitOptions.RemoveEmptyEntries) - Dmitry Bychenko
1
@christian890:不客气!下次请从实际数据开始 :) - Dmitry Bychenko
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接