使用字典键过滤列表

时间:2016-01-23 12:59:39

标签: c# linq dictionary

我想使用List过滤Linq Where / Select,使用Dictionary中的键值,如程序中所示,我当前的解决方案有许多限制。

Dictionary指的是来自UI的用户输入,因此它可能包含一组值而不是给定键的单个值。

任何帮助我找到正确方向的指针。

 public class Business
    {
        public int ID { get; set; }

        public string NAME { get; set; }
    }

void Main()
{
    var businessList = new List<Business>
    {
      new Business {ID = 1,NAME = "A"},
      new Business {ID = 1,NAME = "B"},
      new Business {ID = 1,NAME = "C"},
      new Business {ID = 2,NAME = "D"},
      new Business {ID = 2,NAME = "E"},
      new Business {ID = 2,NAME = "F"},
      new Business {ID = 3,NAME = "G"},
      new Business {ID = 4,NAME = "H"},
      new Business {ID = 4,NAME = "I"},
      new Business {ID = 4,NAME = "J"},
      new Business {ID = 5,NAME = "K"},
      new Business {ID = 5,NAME = "L"}
    };

    var filterDictionary = new Dictionary<string, object>
    {
      {"ID",3},
      {"NAME","G"}
    };

   Expected Result:
   ID    Name
   3      G

   var filterDictionary = new Dictionary<string, object>
    {
      {"ID",new List<int>(){2,3}}
    };

 Expected Result:
   ID    Name
   2      D
   2      E
   2      F
   3      G

Current Solution:

    var result = businessList
                 .Select(x => filterDictionary.ContainsKey(typeof(Business).GetProperty("ID").Name) ?
                             x.ID == (int)filterDictionary[typeof(Business).GetProperty("ID").Name] ? x : null : null                            
                       )
                 .Where(x => x!= null)
                 .Select(x => filterDictionary.ContainsKey(typeof(Business).GetProperty("NAME").Name) ?
                             x.NAME == (string)filterDictionary[typeof(Business).GetProperty("NAME").Name] ? x : null : null
                       );   
}

4 个答案:

答案 0 :(得分:3)

这是一个解决方案:

//Calculate valid IDs from the dictionary
List<int> valid_ids =
    filterDictionary
        .Where(x => x.Key == "ID")
        .SelectMany(x =>
        {
            if (x.Value is int)
            {
                return new[] {(int) x.Value};
            }

            return (IEnumerable<int>) x.Value;

        }).ToList();


//Calculate valid NAMEs from the dictionary
List<string> valid_names =
        filterDictionary
        .Where(x => x.Key == "NAME")
        .SelectMany(x =>
        {
            if (x.Value is string)
            {
                return new[] { (string)x.Value };
            }

            return (IEnumerable<string>)x.Value;

        }).ToList();


IEnumerable<Business> query = businessList;

if (valid_ids.Count > 0)
    query = query.Where(x => valid_ids.Contains(x.ID));

if(valid_names.Count > 0)
    query = query.Where(x => valid_names.Contains(x.NAME));

var result = query.ToList();

答案 1 :(得分:1)

执行此操作的一般方法是使用反射和缓存属性GetMethod来提高性能,因为反射可能非常慢。您还可以使用泛型,以便它可以使用任何类型。以下可能是您正在寻找的东西。

private static List<T> FilterList<T>( IEnumerable<T> source, Dictionary<string, object> propertyFilters )
{
    var properties = propertyFilters.Keys.Distinct()
                                            .ToDictionary( x => x, x => typeof ( T ).GetProperty( x ).GetGetMethod() );

    IEnumerable<T> result = source.ToList();
    foreach ( var propertyFilter in propertyFilters )
    {
        if ( properties.ContainsKey( propertyFilter.Key ) )
        {
            result = result.Where( x =>
            {
                var invoke = properties[propertyFilter.Key].Invoke( x, new object[0] );
                if ( propertyFilter.Value is IList )
                {
                     return ( (IList)propertyFilter.Value ).Cast<object>().Any( f =>
                     {
                         return f.Equals( invoke );
                     } );
                }
                return invoke.Equals( propertyFilter.Value );
            } );
        }
    }
    return result.ToList();
} 

答案 2 :(得分:0)

以下是我的解决方案(返回预期结果):

var result = businessList.Where(bl => filterDictionary
             .Count(fd => bl.GetType().GetProperty(fd.Key).GetValue(bl, null) == fd.Value) > 0);

答案 3 :(得分:-1)

字典只能有唯一的密钥。如果您拥有相同的密钥不止一次,则密钥的值必须是集合。见下面的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Business> businessList = new List<Business>
            {
              new Business {ID = 1,NAME = "A"},
              new Business {ID = 1,NAME = "B"},
              new Business {ID = 1,NAME = "C"},
              new Business {ID = 2,NAME = "D"},
              new Business {ID = 2,NAME = "E"},
              new Business {ID = 2,NAME = "F"},
              new Business {ID = 3,NAME = "G"},
              new Business {ID = 4,NAME = "H"},
              new Business {ID = 4,NAME = "I"},
              new Business {ID = 4,NAME = "J"},
              new Business {ID = 5,NAME = "K"},
              new Business {ID = 5,NAME = "L"}
            };

            Dictionary<int, List<string>> dict = businessList.AsEnumerable()
                .GroupBy(x => x.ID, y => y.NAME)
                .ToDictionary(x => x.Key, y => y.ToList());

       }
        public class Business
        {
            public int ID { get; set; }

            public string NAME { get; set; }
        }

    }
}