从DataTable/DataView中删除空列

4

我有一个DataTable,它从存储过程返回数据(由动态透视语句生成,但我认为这不是相关的)。返回的数据可能有没有数据的列。如何在运行时生成一个排除不返回数据的列的DataView

编辑 - 示例数据

来自:

ID  A  B  C
------------
1   1  2  
2   2  4

to:

ID  A  B
---------
1   1  2  
2   2  4

删除C列。如果数据看起来像这样:

ID  A  B  C
------------
1   1     3
2   2     6

那么B列应该被删除。


你想从表格或视图中删除这些列,还是想删除不含数据的行?能给个小样例吗? - Tim Schmelter
@TimSchmelter 已更新;评论以通知您。 - Zev Spitz
所有的列都是字符串类型吗?在处理“无数据”时,应该将哪个值视为“无数据”,是空字符串、null 还是该类型的默认值? - Tim Schmelter
@TimSchmelter DBNull没问题。 - Zev Spitz
1个回答

3
你可以使用以下方法:

你可以使用这种方法:

public static void RemoveNullColumns(ref DataTable tbl, params string[] ignoreCols)
{
    var columns =  tbl.Columns.Cast<DataColumn>()
        .Where(c => !ignoreCols.Contains(c.ColumnName, StringComparer.OrdinalIgnoreCase));
    var rows = tbl.AsEnumerable();
    var nullColumns = columns.Where(col => rows.All(r => r.IsNull(col))).ToList();
    foreach (DataColumn colToRemove in nullColumns)
        tbl.Columns.Remove(colToRemove);
}

您的示例:

DataTable table = new DataTable();
table.Columns.Add("ID", typeof(int));
table.Columns.Add("A", typeof(int));
table.Columns.Add("B", typeof(int));
table.Columns.Add("C", typeof(int));
table.Rows.Add(1, 1, 2, null);
table.Rows.Add(2, 2, 4, null);

RemoveNullColumns(ref table, "ID");
DataView result = table.DefaultView;

结果(移除"C"列):

ID  A   B
1   1   2
2   2   4

这里有一个重载函数,它不改变原始表格,而是创建一个副本:

public static DataTable RemoveNullColumns(DataTable tbl, params string[] ignoreCols)
{
    DataTable copy = tbl.Copy();
    var columns = copy.Columns.Cast<DataColumn>()
        .Where(c => !ignoreCols.Contains(c.ColumnName, StringComparer.OrdinalIgnoreCase));
    var rows = copy.AsEnumerable();
    var nullColumns = columns.Where(col => rows.All(r => r.IsNull(col))).ToList();
    foreach (DataColumn colToRemove in nullColumns)
        copy.Columns.Remove(colToRemove);
    return copy;
}

第一个方法需要通过 ref 传递 datatable 吗? - Zev Spitz
@ZevSpitzпјҡжҳҜзҡ„пјҢеңЁC#дёӯпјҢеҰӮжһңжӮЁдҪҝз”ЁжңҹжңӣrefеҸӮж•°зҡ„ж–№жі•пјҢеҲҷеҝ…йЎ»жҢҮе®ҡrefгҖӮиҝҷеҸӘжҳҜиЎЁжҳҺиҜҘж–№жі•е°Ҷдҝ®ж”№жӮЁзҡ„иЎЁзҡ„жҢҮзӨәгҖӮ - Tim Schmelter
按照这种推理,静态的 Array.Sort 方法也应该通过引用传递第一个参数。难道不是已经理解当将对象传递到方法中时,即使该方法无法用相同类型的另一个对象替换该对象,该方法可能会修改对象的属性吗? - Zev Spitz
@ZevSpitz:你说得对,我的ref理解并不是固定的。你也可以去掉ref。在这种情况下,我使用它有两个原因:1)它清楚地表明该方法删除列(而不仅仅是像Array.Sort一样排序),2)它允许重载两种方法。如果没有ref,编译器将不允许它们,因为它们具有相同的参数。总的来说,你说得对,在修改传递对象的每个方法上使用ref既不是必要的,也不是常见的做法。 - Tim Schmelter

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