C# - 将对象列表转换为包含多个对象属性的数组
Posted
技术标签:
【中文标题】C# - 将对象列表转换为包含多个对象属性的数组【英文标题】:C# - convert a list of objects to an array of multiple of the object's properties 【发布时间】:2021-02-15 22:54:08 【问题描述】:我有这个 JSON 字符串:
"countries": [
"countryCode": "AR",
"country": "Argentina"
,
"countryCode": "BR",
"country": "Brazil"
]
还有这个 Country 类和国家列表:
List<Country> countries get; set;
class Country
public string country get; set;
public string countryCode get; set;
我需要创建一个包含国家代码和名称的二维对象数组:
propVal[0, 0] = "AR";
propVal[0, 1] = "Argentina";
propVal[1, 0] = "BR";
propVal[1, 1] = "Brazil";
.
.
.
现在我正在“手动”遍历国家列表并构建对象数组:
int row = 0;
foreach (Country country in countries)
propVal[row, 0] = country.countryCode;
propVal[row, 1] = country.country;
row++;
远景是有一个通用的方式,适用于其他 JSON,假设有 3 个或更多属性,并产生一个 x 维对象数组。
有没有一种 LINQ 方法可以做到这一点?我知道this 线程,它处理一个对象属性并且LINQ 方法是countries.Select(x=>x.country).ToArray()
,但在我的情况下需要多个属性。
感谢您的帮助!
【问题讨论】:
这似乎是一个 X/Y 问题。为什么你需要一个多维数组,而不是一个类(国家)列表 因为生成的多维对象数组会写入Excel表格。 你可以使用反射来做到这一点。但它不会很漂亮......使用DataTable怎么样? 没有内置的 linq 方法来生成多维数组 - 这有一个很好的理由:数组的维数必须在编译时知道 - 所以你不能有一个方法可以返回一个任意维数的数组。方法可以做到这一点的唯一方法是返回dynamic
或 object
- 这为各种问题打开了大门 - 主要问题是应该是编译时错误的错误被推送到运行时。
正常序列化,然后循环填充二维数组。你也可以喜欢 JObject,但我不会打扰。像往常一样序列化它
【参考方案1】:
如果你真的需要构建一个二维数组,你可以通过这种方式动态排列数据:
var data = new List<Country>
new Country country = "Brazil", countryCode = "BR",
new Country country = "Argentina", countryCode = "AR"
;
// declare all the property accessors you want from your type (Country)
// it can be built by reflection
var accessors = new List<Func<Country, string>>
x => x.country,
x => x.countryCode
;
// declaring the 2D array,
// first dimension length is the size of the data (number of countries)
// second dimension length is the number of fields from the data type (Country)
var propVal = new string[data.Count, accessors.Count];
// projecting each element with each field accessor (cartesian product)
// that is (countries.Count) x (accessors.Count)
// (0,0,"Brazil") (0,1,"BR") (1,0,"Argentina") (1,1,"AR")
var flatenData = data.SelectMany((country, i) => accessors.Select((f, j) => (i, j, field: f(country))));
// filling the 2D array
foreach (var tuple in flatenData)
propVal[tuple.i, tuple.j] = tuple.field;
如果我们显示二维数组:
// displaying the 2D array
for (var i = 0; i < propVal.GetLength(0); i++)
for (var j = 0; j < propVal.GetLength(1); j++)
Console.WriteLine($"[i,j] = propVal[i,j]");
/*
[0,0] = Brazil
[0,1] = BR
[1,0] = Argentina
[1,1] = AR
*/
【讨论】:
【参考方案2】:我建议从多维数组切换到数组数组 - 它更容易实现,并且很可能满足您在此任务中的所有需求。
这是您需要做的。假设您有一些具有一堆公共属性的通用类,您希望以这种方式序列化:
public class A
public string P1 get; set;
public string P2 get; set;
public string P3 get; set;
您可以像这样获取该类的属性集合:
var props = typeof(A).GetProperties();
然后,您需要做的就是对您的项目集合进行 LINQ 并获取每个属性的值:
var result = items.Select(item =>
props.Select(prop =>
prop.GetValue(item)
.ToString())
.ToArray())
.ToArray();
当然,items
是 List<A>
。
就是这样。你有自己的数组。
如果你觉得你确实需要它是一个 2D 数组,那么你必须像 here 那样实现转换。
【讨论】:
以上是关于C# - 将对象列表转换为包含多个对象属性的数组的主要内容,如果未能解决你的问题,请参考以下文章
在c#中将对象列表转换为数组-“x => x.Name”语法是啥意思? [复制]
如何使用 Newtonsoft.Json 将包含数组数组的 json 对象解析为 C# 中的对象列表?