【问题标题】:Searching an IEnumerable<dynamic>搜索 IEnumerable<dynamic>
【发布时间】:2026-01-10 21:25:01
【问题描述】:

我有一个枚举如下:

 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 列表/集合/哈希表等)的最佳方式,也是从集合中查询信息的最佳方式。该集合最多将是一页数据(25 行)。 任何代码 sn-ps 和数据结构都可以以超快速有效的方式搜索数据。假设搜索词是“包含”匹配而不是完美匹配。

【问题讨论】:

  • “超快”和“动态”通常不会出现在同一个上下文中 :)
  • 必须有dynamics 的序列吗?看起来一系列字符串数组会更好地为您服务。
  • 这是数据的结构,我无法更改它。

标签: c# search dynamic find


【解决方案1】:

那些是匿名类型;匿名类型是一种编译器特性,因此布局在编译时是固定的,因此它们不会发生变化。我建议:不要使用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(...)


编辑:我认为的评论让我更清楚地理解它;我正在描绘一个不透明的方法,它返回实际上是 POCO 类型(不是动态类型)的 IEnumerable&lt;dynamic&gt;,我们想要检查字符串成员(任意名称)是否匹配。我们应该可以通过反射来做到这一点,但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"};
}

【讨论】:

  • 我的返回类型是 IEnumerable,因此我无法执行代码。
  • @chugh97 我怀疑你可能想在更多的上下文中展示这一点,即返回类型的方式等,以及调用者希望如何使用它。目前,(缺乏)上下文非常令人困惑。
  • 如果用户搜索例如 ACC01 的搜索词,则 25 行 IEnumerable 其中 dynamic 是基础数据表,例如此实例为 6 列。在所有 6 列和所有 25 行中搜索 ACC01。如果找到匹配项,则返回包含行号的行和找到包含匹配项的数据的列。例如,如果 25 行中的列有一列是“My ACC No is ACC01020345”,因为字符串中包含 AAC01,列名、行号和值将返回给用户。
  • 我的返回类型是动态集合,因为我有数百个使用相同功能的表,我无法控制更改它。
  • 列名在不同的表实例中会有所不同。所以上面的代码很好,只是动态对象的属性可能不同。是否可以让它非常通用,就像通过动态属性循环一样
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    在我的情况下,解决方案是投射我的

    IEnumerable<dynamic>
    

    作为

    IEnumerable<IDictionary<String, Object>>
    

    但我认为它只适用于通过 dapper 获取的数据,例如:

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

    我不知道它的工作速度有多快,但我希望它能帮助你(或某人,看到这个问题是不久前发布的)。

    【讨论】: