搜索IEnumerable <dynamic> </dynamic>

时间:2012-08-07 19:26:53

标签: c# search dynamic find

我有一个可枚举的如下:

 IEnumerable<dynamic> collection = new 
 {  
    column1 = "1", column2 = "name", column3= "somevalue" 
 }, 
 new 
 { 
    column1 = "2",   column2 = "name2", column3= "somevalue2" 
 },
 new 
 { 
    column1 = "3", column2 = "name3", column3= "somevalue3" 
 }

等等......动态类型中的列数也可能不同。列的数量可能更多或更少。

现在,如果我想搜索此IEnumerable集合,例如somevalue2,我需要以下信息 在列“column2”中的第2行(假设column1始终是主键)中找到。 这是将此动态集合转换为数据结构(.NET List / Collection / Hashtable等)的最佳方式,也是查询集合中信息的最佳方式。该集合最多将是一页数据(25行)。 任何代码片段和数据结构都可以实现超快速有效的数据搜索方式。假设搜索词是“包含”匹配而不是完美匹配。

3 个答案:

答案 0 :(得分:3)

这些是匿名类型;匿名类型是一种编译器功能,因此在编译时布局是 fixed rigid ,因此它们不会发生变化。我建议:不要使用dynamic。例如:

 var arr = new[] {
   new { column1 = "1", column2 = "name", column3= "somevalue" }, 
   new { column1 = "2", column2 = "name2", column3= "somevalue2" },
   new { column1 = "3", column2 = "name3", column3= "somevalue3" }
 };

这是强类型和明确定义的。您可以使用常规操作,例如:

var item2 = arr.FirstOrDefault(x => x.column1 == "2");

再次,所有静态类型。

如果你想搜索所有列,那么我会建议像字典更好的东西:

 var arr = new[] {
   new Dictionary<string,string> { {"column1", "1"}, ... }, 
   new Dictionary<string,string> { {"column1", "2"}, ... }, 
   new Dictionary<string,string> { {"column1", "3"}, ... }, 
 };

因为您可以查看.Values.Contains(...)


编辑:通过评论我认为我更清楚地理解它;我正在想象一个返回IEnumerable<dynamic>的opaque方法,它实际上是POCO类型(不是动态类型),我们想检查匹配的字符串成员(任意名称)。我们应该能够通过反射来做到这一点,但FastMember会使速度更快:

static void Main()
{
    string search = "ame2";

    int rowIndex = 0;
    string[] names = null;
    TypeAccessor accessor = null;
    foreach(object row in GetData())
    {
        if(names == null)
        { // first row; get the property-names and build an accessor
            names = (from prop in row.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
                     where prop.PropertyType == typeof (string)
                     select prop.Name).ToArray();
            accessor = TypeAccessor.Create(row.GetType());
        }

        foreach(var name in names)
        {
            var val = accessor[row, name] as string;
            if(val != null && val.Contains(search))
            {
                Console.WriteLine("row {0}, col {1}, val {2}", rowIndex, name, val);
            }
        }
        rowIndex++;
    }
}
static IEnumerable<dynamic> GetData()
{
    yield return new {column1 = "1", column2 = "name", column3 = "somevalue"};
    yield return new {column1 = "2", column2 = "name2", column3 = "somevalue2"};
    yield return new {column1 = "3", column2 = "name3", column3 = "somevalue3"};
}

答案 1 :(得分:0)

如果你真的希望它们是每个项目中具有不同列的动态对象,你可以这样声明:

IEnumerable<dynamic> collection = new dynamic[]
                                        {
                                            new  
                                                {
                                                    column1 = "1",
                                                    column2 = "name",
                                                    column3 = "somevalue"
                                                },
                                            new
                                                {
                                                    column1 = "2",
                                                    column2 = "name2"
                                                },
                                            new
                                                {
                                                    column1 = "3",
                                                    column2 = "name3",
                                                    column3 = "somevalue3",
                                                    column4 = "fourthValue"
                                                }
                                        };

将其转换为列表很简单:

// create a list
var list = new List<dynamic>(collection);

查找项目有点复杂,因为属性可能不存在:

// find an item
var itemOne = collection.Where(i =>
                                    {
                                        try
                                        {
                                            if (i.column1 == "1")
                                            {
                                                return true;
                                            }
                                        }
                                        catch
                                        {
                                            // ignore error, column doesn't exist
                                        }
                                        return false;
                                    });

答案 2 :(得分:0)

我不知道你的IEnumerable下面究竟隐藏了什么,但最近我不得不搜索Dapper从某些查询返回的结果,这些查询作为动态的IEnumerable返回(这是我遇到这个问题的方式)。

在我的情况下,解决方案是施展我的

IEnumerable<dynamic>

作为

IEnumerable<IDictionary<String, Object>>

但是我认为它只适用于数据取样,如:

db.Connection.Query(myQuery)

对于这个特殊问题,这样的事情可能会起作用(尚未测试):

IEnumerable<IDictionary<String, Object>> data = YourData.Cast<IDictionary<String, Object>>();
var row = data.SingleOrDefault(x => x.Where(y => y.Value.ToString() == "somevalue2"));

我不知道这会有多快,但我希望它会帮助你(或某人,看到这个问题刚刚发布)。