LINQ从集合A中选择不在集合B中的项目

时间:2010-07-22 12:52:08

标签: c# linq except

我想对一组项目执行Except操作。

代码是这样的:

IEnumerable<DataGridViewColumn> dgvColumns = dataGridView.Columns.OfType<DataGridViewColumn>();
IEnumerable<DataColumn> dsColumns = dataSet.Tables[0].Columns.OfType<DataColumn>();

现在,如何从dataSet.Tables [0]中选择不在dgvColumns中的列? 我知道DataGridView中的Columns与DataSet中的Columns类型不同。我想只获取一部分常见值。像这样:

        var ColumnsInDGV = from c1 in dgvColumns
                           join c2 in dsColumns on c1.DataPropertyName equals c2.ColumnName
                           select new { c1.HeaderText, c1.DataPropertyName, c2.DataType, c1.Visible };

上面的代码选择了两个集合中的“列”。所以我认为我将在DataSet中创建另一组“列”:

  var ColumnsInDS = from c2 in dsColumns select new { HeaderText = c2.ColumnName, DataPropertyName = c2.ColumnName, c2.DataType, Visible = false };

现在我将能够执行除此之外:

var ColumnsOnlyInDS = ColumnsInDS.Except<ColumnsInDGV>;

但我收到两个错误:

  1. 找不到类型或命名空间名称“ColumnsInDGV”(您是否缺少using指令或程序集引用?)
  2. 无法将方法组分配给隐式类型的局部变量
  3. 所以解决方案是构建一个类然后使用它而不是隐含的类型局部变量。但我认为仅仅因为这个原因开发一个班级是一个不必要的开销。

    这个问题还有其他解决办法吗?

1 个答案:

答案 0 :(得分:3)

你几乎得到了它。你只需要写:

// use () to pass a parameter
// type (should) be inferred
var ColumnsOnlyInDS = ColumnsInDS.Except(ColumnsInDGV);

而不是:

// do not use <> - that passes a type parameter;
// ColumnsInDGV is not a type
var ColumnsOnlyInDS = ColumnsInDS.Except<ColumnsInDGV>;

更新:因此,上述实际上不起作用,因为Except依赖于比较两个序列中的项目是否相等;很明显,您的匿名类型没有覆盖object.Equals,因此您创建此类型的每个对象都被视为一个不同的值。试试这个*:

var dgvColumns = dataGridView.Columns.Cast<DataGridViewColumn>();
var dsColumns = dataSet.Tables[0].Columns;

// This will give you an IEnumerable<DataColumn>
var dsDgvColumns = dgvColumns
    .Where(c => dsColumns.Contains(c.DataPropertyName))
    .Select(c => dsColumns[c.DataPropertyName]);

// Then you can do this
var columnsOnlyInDs = dsColumns.Cast<DataColumn>().Except(dsDgvColumn);

*注意:Where的上述表达式中的dsDgvColumnsSkipWhile更有意义,因为它会将指定的过滤器应用于所有结果。 SkipWhile只会应用过滤器,只要它是真的,然后就会停止应用它。换句话说,如果DataGridViewColumn未绑定到DataSet的{​​{1}}位于DataGridView开头,它就会有用;但不是如果它在中间或结尾。