动态Where条件

时间:2012-03-14 16:36:08

标签: c# linq lambda

我有一点问题:)我有一个列表,其中一些参数是重复的。我必须删除它。我不能使用Distinct因为我必须只看到某些领域(不是全部)。我认为使用lambda epxressions是很好的选择。

我在我的对象上有一个我工作的声明,不一样,但想法是相似的。

var keys = new string[] {"column1", "column2"};
var repeatedValues = new object[] {5, 15};

var values = new List<Dictionary<string, object>>();

//MAKE FAKE DOUBLE
values.Add(new Dictionary<string, object> { 
            { "column1", 5 }, { "column2", 15 }, { "column3", "test" }, 
            { "column4", "test1" } });

for (int i = 0; i < 10; i++)
{
   values.Add(new Dictionary<string, object> {
               {"column1", i}, {"column2", 10 + i},  "column3", "test"}, 
               {"column4", "test1"}});
}

keys列始终与repeatedValues具有相同的长度 - 但是已更改,有些长度为1,其他2,3,5。不超过5

密钥类似于数据库表上的primaryKeys。它非常相似。所以我们在“主键列”中寻找重复项 - 我认为这是一个很好的比较。

我们在该示例中看到复制在“column1”中具有值5,在“column2”中具有值15。我以前怎么说我必须删除它,但在我必须计算重复的项目之前。

我尝试做那样的代码(我知道func方法awalys失败因为(对象)1 ==(对象)1总是返回false,但这是示例:

Expression expression = null;

for (int i = 0; i < keys.Length; i++)
{
    Expression<Func<Dictionary<string, object>, bool>> exp = x => x[keys[i]] == repeatedValues[i];

    if (expression == null)
      expression = exp.Body;
    else
      expression = Expression.AndAlso(expression, exp.Body);
}

var parameterExpression = Expression.Parameter(typeof (Dictionary<string, object>), "x");

var lamba = Expression.Lambda<Func<Dictionary<string, object>, bool>>(expression, parameterExpression);

var res = lamba.Compile();
var counts = queryLis.Count(res);

但是编译器给了我一个例外 变量'x'类型'System.Collections.Generic.Dictionary`2 [System.String,System.Object]'从范围''引用,但未定义

这样可以做到这一点吗?

(不是关于例外)在其他步骤中可能表达式要求例如repeatedValues [i](在for之后)并且它将不知道它是什么?

2 个答案:

答案 0 :(得分:0)

您需要传递原始表达式引用的相同Expression.Parameter 制作一个名称相同的新Expression.Parameter是不够的。

答案 1 :(得分:0)

我不知道你为什么要乱用Expression等。如果我理解正确,那么您实际上是复制关系数据库情况,每个值条目都是一行数据,其中列表示字段名称。如果是这种情况,那么您也可以从数据库书中获取一个页面并使用索引。在您的第一个片段之后,您可以获得如下所示的清理列表:

// testing for duplicates
List<Dictionary<string, object>> duplicates = new List<Dictionary<string, object>>();
List<string> index = new List<string>();
foreach (var value in values)
{
    List<string> keyValues = new List<string>();
    foreach (string key in keys)
    {
        keyValues.Add(value[key].GetHashCode().ToString());
    }
    string hash = string.Join(",", keyValues.ToArray());
    if (index.Contains(hash))
        duplicates.Add(value);
    else
        index.Add(hash);
}

var cleanList = values.Except(duplicates);

编辑:更改示例,以便每次都将哈希值放在相同的列顺序中。