【问题标题】:Convert IEnumerable object list to list of object arrays C#将 IEnumerable 对象列表转换为对象数组列表 C#
【发布时间】:2015-05-09 14:19:00
【问题描述】:

我有一个具有大量属性的对象模型。这些属性的值是从数据库中提取的,以提供IEnumerable 列表或数组,如下所示:

var obj = context.Model.Where(x => idList.Contains(x.Id)).ToList();

这给出了此结构中的 Json 输出 blob:

[{ Prop1: 57, Prop2: 2, Prop3: 25 ... },
 { Prop1: 23, Prop2: 4, Prop3: 20 ....},
 { Prop1: 15, Prop2: 6, Prop3: 32 ....},
 ... ]

有没有办法可以设置 linq 查询来提取这种形式的数据:

{ Prop1: [57,23,15, ...],
  Prop2: [2,4,6, ....],
  Prop3: [25,20,32, ...],
  ... }

换句话说,我想要对象数组的集合而不是对象数组

【问题讨论】:

  • 什么 context.Model.Where(x => idList.Contains(x.Id)).ToArray();给你?
  • 是的,我们需要模型类的详细信息
  • Fabian 和 dbc 都明白了这一点。更棒的是,他们的两个解决方案都可以处理通用对象结构和可为空的类型。

标签: c# arrays linq object


【解决方案1】:

如果您使用的是 Json.NET,则可以使用LINQ to JSON 以完全通用的方式重构 JSON,而无需编写自己的反射代码:

        var jArray = JArray.FromObject(obj);    // obj must serialized to an array; throw an exception otherwise.
        var jObj = new JObject(jArray           // Allocate new outer JSON object
            .Cast<JObject>()                    // All array element must be json objects
            .SelectMany(o => o.Properties())
            .GroupBy(p => p.Name, p => p.Value) // Group all array element properties by name
            .Select(g => new JProperty(g.Key, g))); // Add an array-valued property to the new outer object.
        var json = jObj.ToString();
        Debug.WriteLine(json);

给定以下输入obj

        var obj = new List<object>
        {
            new { Prop1 = 57, Prop2 = 2, Prop3 = 25 },
            new { Prop1 = 23, Prop2 = 4, Prop3 = 20 },
            new { Prop1 = 15, Prop2 = 6, Prop3 = 32 },
        };

生成以下 JSON:

{"Prop1":[57,23,15],"Prop2":[2,4,6],"Prop3":[25,20,32]}

或者,如果您的 obj 是强类型的,您可以手动创建一个中间 anonymous type 用于输出,如下所示:

        var newObj = new { Prop1 = obj.Select(i => i.Prop1), Prop2 = obj.Select(i => i.Prop2), Prop3 = obj.Select(i => i.Prop3) };

然后,给定以下输入obj

        var obj = new[] 
        {
            new [] { 57,2,25 },
            new [] { 23,4,20 },
            new [] { 15,6,32 },
        }
        .Select(a => new { Prop1 = a[0], Prop2 = a[1], Prop3 = a[2] });

生成相同的 JSON。

【讨论】:

    【解决方案2】:

    如果你想通用的话,我认为你不能用纯 Linq 做到这一点。您至少需要使用一些反射来循环您的属性。

    下面的代码应该做你想做的:

            var list = new List<object> {new { A = 1, B = 2, C = 3}, new {A = 1, B = 1, D = 1}};
    
            var result = new ExpandoObject(); 
    
            var list1 = list.Aggregate<object, ExpandoObject>(result, (res, a) =>
            {
                foreach (var prop in a.GetType().GetProperties())
                {
                    object val = prop.GetValue(a);
    
                    var x = res as IDictionary<string, Object>;
                    object o;
                    if (!x.TryGetValue(prop.Name, out o))
                    {
                        o = new List<object>();
                        x.Add(prop.Name, o);
                    }
    
                    ((List<object>)o).Add(val);
                }
    
                return res;
            });
    
                var inputJson = Newtonsoft.Json.JsonConvert.SerializeObject(list);
    
            var outputJson = Newtonsoft.Json.JsonConvert.SerializeObject(list1);
    

    对于这个输入:[{"A":1,"B":2,"C":3},{"A":1,"B":1,"D":1}]

    它给出以下输出:{"A":[1,1],"B":[2,1],"C":[3],"D":[1]}

    当然,如果您有强类型类,则不需要使用反射。您还可以传递类类型以自行聚合和编写映射。

    【讨论】:

    • 这也有效 - 感谢 Fabian。 dbc 得到了优雅的 linq 查询的巧克力
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 2013-12-02
    相关资源
    最近更新 更多