简体   繁体   English

LINQ查询和字符串数组

[英]LINQ query and Array of string

I have a array of string say: 我有一个string数组说:

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

In which I can use the below query to get the values by specifying the values is query ie RowField and RowField1 : 我可以在其中使用以下查询通过指定查询的值(即RowFieldRowField1来获取值:

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

But if suppose I have many values in the Array like: 但是如果假设我在Array有很多值,例如:

String[] Fields= new String[]
{
    RowField,
    RowField1,
    RowField2,
    .......
    RowField1000
};
  • How can I use the query here without specifying each of the rowfield in the query? 如何在不指定查询中每个行字段的情况下在此处使用查询?
  • How can i iterate through the array items inside the LINQ? 我如何遍历LINQ中的数组项?
var Result = (
    from x in _dataTable.AsEnumerable()
    select (
        from y in Fields
        select new KeyValuePair<string, object>(y, x))
        .ToDictionary())
    .Distinct(DictionariesComparer);

You'll also need to write your own .ToDictionary() extension method and DictionariesComparer method (as Dictionary doesn't implement IEquatable ). 您还需要编写自己的.ToDictionary()扩展方法和DictionariesComparer方法(因为Dictionary不实现IEquatable )。

Essentially, you want to retrieve specific fields from a DataTable without hardcoding the field names. 本质上,您想从数据表中检索特定字段,而无需对字段名进行硬编码。

The following code will return a single dictionary object per row with the fields you specify in your array. 以下代码将每行返回一个字典对象,其中包含您在数组中指定的字段。 There is no need to create additional extension methods or comparers: 无需创建其他扩展方法或比较器:

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

The inner select picks the field values you need from each table row and stores them in the projection variable. 内部选择从每个表行中选择您需要的字段值,并将它们存储在投影变量中。 The outer select converts this variable in a Dictionary 外部选择将此变量转换为Dictionary

You can iterate over the result to get specific fields like this: 您可以遍历结果以获取特定字段,如下所示:

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

EDIT: The above code doesn't return distinct values. 编辑:上面的代码不会返回不同的值。 It is possible to return distinct values without writing a special comparer using group by but the code is not very pretty: 无需使用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));  

The Aggregate creates a new projection whose Name and Value properties are the concatenation of all name and value fields. 聚合将创建一个新的投影,其名称和值属性是所有名称和值字段的串联。 The result of the aggregate is used to group all rows and return the first row of each group. 聚合的结果用于对所有行进行分组,并返回每组的第一行。 It works but it is definitely ugly. 它有效,但是绝对难看。

It would be better to create a simple DictionaryComparer like the following code: 最好像下面的代码那样创建一个简单的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;
        }
    }

This allows you to write: 这使您可以编写:

        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>());

There is no foreach linq expression. 没有foreach linq表达式。 I typically create my own extension method 我通常创建自己的扩展方法

Something along the lines of: 类似于以下内容:

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

However beware if you're planning on using this with Linq2SQL as it could create a lot of db hits! 但是请注意,如果您打算将它与Linq2SQL一起使用,因为它可能会产生很多数据库匹配!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM