代码之家  ›  专栏  ›  技术社区  ›  Wodzu

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

  •  0
  • Wodzu  · 技术社区  · 15 年前

    我想对一组项目执行“除”操作。

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

    现在,如何从dataSet.Tables[0]中选择不在dgvColumns中的列? 我知道DataGridView中的列与DataSet中的列的类型不同。我只想选取公共值的一个子集。这样地:

            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 };
    

    上面的代码选择两个集合中的“列”。所以我想我会在数据集中创建另一组“列”:

      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. 无法将方法组赋给隐式类型的局部变量

    因此,解决方案是构建一个类,然后使用它而不是隐式类型的局部变量。但是我认为仅仅因为这个原因开发一个类是不必要的开销。

    这个问题还有别的解决办法吗?

    1 回复  |  直到 15 年前
        1
  •  3
  •   Dan Tao    15 年前

    你就快成功了。你只需要写:

    // 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 在上面的表达式中 dsDgvColumns 比…更有意义 SkipWhile 因为它会将指定的筛选器应用于 全部的 结果。 船夫 将只应用过滤器,只要它是真的,然后将停止应用它。换句话说,如果你的 DataGridViewColumn DataSet 开始 DataGridView ; 但如果是在中间或最后就不会了。