LINQ查询和字符串数组

时间:2012-02-15 10:46:16

标签: c# .net linq datatable

我有一组string说:

String[] Fields=new String[]{RowField,RowField1}

我可以使用以下查询通过指定值来获取值,即查询RowFieldRowField1

var Result = (
    from x in _dataTable.AsEnumerable()
    select new
    {
        Name = x.Field<object>(RowField), 
        Name1 = x.Field<object>(RowField1)
    })
    .Distinct();

但是假设我在Array中有很多值,比如:

String[] Fields= new String[]
{
    RowField,
    RowField1,
    RowField2,
    .......
    RowField1000
};
  • 如何在不指定查询中的每个字段的情况下使用此处的查询?
  • 如何遍历LINQ中的数组项?

3 个答案:

答案 0 :(得分:3)

var Result = (
    from x in _dataTable.AsEnumerable()
    select (
        from y in Fields
        select new KeyValuePair<string, object>(y, x))
        .ToDictionary())
    .Distinct(DictionariesComparer);

您还需要编写自己的.ToDictionary()扩展方法和DictionariesComparer方法(因为Dictionary未实现IEquatable)。

答案 1 :(得分:2)

实际上,您希望从DataTable中检索特定字段,而无需对字段名称进行硬编码。

以下代码将返回每行一个字典对象以及您在数组中指定的字段。无需创建其他扩展方法或比较器:

var result = (from row in _dataTable.AsEnumerable()
                 let projection = from fieldName in fields
                      select new {Name = fieldName, Value = row[fieldName]}
                 select projection.ToDictionary(p=>p.Name,p=>p.Value));            

内部选择从每个表行中选择所需的字段值,并将它们存储在投影变量中。外部选择在Dictionary

中转换此变量

您可以迭代结果以获取如下所示的特定字段:

foreach (var row in result)
{
    Console.WriteLine(row["field1"]);
}

修改 上面的代码不返回不同的值。可以返回不同的值,而无需使用 group by 编写特殊的比较器,但代码不是很漂亮:

var result = (from row in table.AsEnumerable()
                let projection = from fieldName in fields
                                select new { Name = fieldName, Value = row[fieldName] }
                group projection by projection.Aggregate((v, p) =>
                    new {
                        Name = v.Name + p.Name, 
                        Value = (object)String.Format("{0}{1}", v.Value, p.Value)
                    }) into g
                select g.FirstOrDefault().ToDictionary(p=>p.Name,p=>p.Value));  

Aggregate创建一个新投影,其Name和Value属性是所有name和value字段的串联。聚合的结果用于对所有行进行分组并返回每个组的第一行。它有效,但绝对是丑陋的。

最好像下面的代码一样创建一个简单的DictionaryComparer:

    public class DictionaryComparer<TKey,TValue>: EqualityComparer<Dictionary<TKey,TValue>>
    {
        public override bool Equals(Dictionary<TKey, TValue> x, Dictionary<TKey, TValue> y)
        {
            //True if both sequences of KeyValuePair items are equal
            var sequenceEqual = x.SequenceEqual(y);
            return sequenceEqual;
        }

        public override int GetHashCode(Dictionary<TKey, TValue> obj)
        {
            //Quickly detect differences in size, defer to Equals for dictionaries 
            //with matching sizes
            return obj.Count;
        }
    }

这允许你写:

        var result = (from row in table.AsEnumerable()
                     let projection = from fieldName in fields
                                      select new {Name = fieldName, Value = row[fieldName]}                                                                                    
                     select projection.ToDictionary(p=>p.Name,p=>p.Value))
                     .Distinct(new DictionaryComparer<string, object>());

答案 2 :(得分:0)

没有foreach linq表达。我通常会创建自己的扩展方法

有些事情:

public static void Foreach<T>(this IEnumerable<T> items, Action<T> action)
{
 foreach(T t in items)
 {
  action(t);
 }
}

但是要注意你是否打算在Linq2SQL上使用它,因为它可能会产生大量的db命中!