如何解决IEnumerable<object[]> 和 IEnumerable<object>[] 之间的优雅转换
有什么方法可以将 IEnumerable<int[]>
转换为 IEnumerable<int>[]
吗?具体来说,我有以下 IEnumerable:
IEnumerable<int[]> data = new List<int[]>()
{
new int[]{1,11},new int[]{2,22},new int[]{3,33},new int[]{4,44},// ...
// ...
};
我想把它变成以下形状:
IEnumerable<int>[] data = new List<int>[]
{
new List<int>(){1,2,3,4 },new List<int>(){11,22,33,44}
};
到目前为止,我想出的唯一解决方案如下:
public static IEnumerable<int>[] Convert(IEnumerable<int[]> data)
{
var length = data.First().Length;
var output = new List<int>[length];
for (int i = 0; i < length; i++)
output[i] = new List<int>();
foreach (var entry in data)
{
for (int i = 0; i < length; i++)
{
output[i].Add(entry[i]);
}
}
return output;
}
虽然这并不理想,因为我需要遍历整个数据集。所需的解决方案是利用 LINQ 或内置迭代器模式功能 (yield return
)。这个问题有没有更好的解决方案?
解决方法
如果您不介意 data
的多个枚举,您可以这样做:
public static IEnumerable<int>[] Convert(IEnumerable<int[]> data)
{
var length = data.First().Length;
var output = new IEnumerable<int>[length];
for (int i = 0; i < length; i++)
{
output[i] = CustomEnumerable(i);
}
return output;
IEnumerable<int> CustomEnumerable(int index)
{
foreach (var entry in data)
{
yield return entry[index];
}
}
}
如您所见,我返回的是自定义 IEnumerable<int>
,而不是填充列表,这些是使用本地迭代器函数(使用 yield return
)创建的。
如果你只关心迭代 data
一次,你可以这样做:
IEnumerable<int>[] Convert(IEnumerable<int[]> data)
{
var found = new List<int[]>();
using var enumerator = data.GetEnumerator();
var proxy = ProxyEnumerable();
var length = proxy.First().Length;
var output = new IEnumerable<int>[length];
for (int i = 0; i < length; i++)
{
output[i] = CustomEnumerable(i);
}
return output;
IEnumerable<int> CustomEnumerable(int index)
{
foreach (var entry in proxy)
{
yield return entry[index];
}
}
IEnumerable<int[]> ProxyEnumerable()
{
foreach (var value in found)
{
yield return value;
}
while (enumerator.MoveNext())
{
var value = enumerator.Current;
found.Add(value);
yield return value;
}
}
}
在这里,我添加了另一个 IEnumerable<int[]>
,当我们对其进行迭代时,它正在填充缓存 List<int[]>
。这样 data
只迭代一次,后续迭代使用缓存。
我对 LINQ 有一个简短的建议。通过下面的例子,你可以得到一个锯齿状的数组
var maxLength = data.Max(x => x.Length);
var converted = new IEnumerable<int>[maxLength]
.Select((dst,index) => data
.Select(src => src.Length > index ? src[index] : default)
.Where(n => n != default));
有了这个,你可以把你的源数组切成矩阵
var minLength = data.Min(x => x.Length);
var converted = new IEnumerable<int>[minLength]
.Select((dst,index) => data
.Select(src => src[index]));
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。