2024-04-14 06:00:02

c#中的数组片

你是怎么做到的?给定一个字节数组:

byte[] foo = new byte[4096];

我如何得到数组的前x字节作为一个单独的数组?(具体来说,我需要它作为一个IEnumerable<byte>)

这是用于使用Sockets的。我认为最简单的方法是数组切片,类似于perl语法:

@bar = @foo[0..40];

将前41个元素返回到@bar数组中。c#中是否有我遗漏的东西,或者有其他我应该做的事情?

LINQ对我来说是一个选择。NET 3.5),如果有帮助的话。


当前回答

数组是可枚举的,所以你的foo已经是IEnumerable<字节>本身。 简单地使用像Take()这样的LINQ序列方法来获得你想要的结果(不要忘记在使用System.Linq;时包含LINQ命名空间):

byte[] foo = new byte[4096];

var bar = foo.Take(41);

如果你真的需要一个来自任何IEnumerable<byte>值的数组,你可以使用ToArray()方法。但在这里,情况似乎并非如此。

其他回答

如果你想要IEnumerable<byte>,那么只是

IEnumerable<byte> data = foo.Take(x);

在c# 7.2中,您可以使用Span<T>。新制度的好处。内存系统的优点是它不需要到处复制数据。

你需要的方法是切片:

Span<byte> slice = foo.Slice(0, 40);

现在很多方法都支持Span和IReadOnlySpan,所以使用这个新类型非常简单。

请注意,在撰写本文时,Span<T>类型在。net的最新版本(4.7.1)中还没有定义,因此要使用它,您需要安装系统。来自NuGet的内存包。

从c# 8.0/开始。Net Core 3.0

数组切片将被支持,同时添加了新的类型Index和Range。

范围结构文档 索引结构文档

Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine($"{a[i1]}, {a[i2]}"); // "3, 6"

var slice = a[i1..i2]; // { 3, 4, 5 }

以上代码样本摘自c# 8.0博客。

注意,^前缀表示从数组的末尾开始计数。如文档示例所示

var words = new string[]
{
                // index from start    index from end
    "The",      // 0                   ^9
    "quick",    // 1                   ^8
    "brown",    // 2                   ^7
    "fox",      // 3                   ^6
    "jumped",   // 4                   ^5
    "over",     // 5                   ^4
    "the",      // 6                   ^3
    "lazy",     // 7                   ^2
    "dog"       // 8                   ^1
};              // 9 (or words.Length) ^0

Range和Index也适用于切片数组之外,例如循环

Range range = 1..4; 
foreach (var name in names[range])

将循环1到4项


请注意,在撰写本文时,c# 8.0还没有正式发布 c# 8。. x和。net Core 3。x现已在Visual Studio 2019及以后版本中可用

如果你不想添加LINQ或其他扩展,只需:

float[] subArray = new List<float>(myArray).GetRange(0, 8).ToArray();

c# 8现在(从2019年开始)支持范围,这让你更容易实现Slice(类似于JS语法):

var array = new int[] { 1, 2, 3, 4, 5 };
var slice1 = array[2..^3];    // array[new Range(2, new Index(3, fromEnd: true))]
var slice2 = array[..^3];     // array[Range.EndAt(new Index(3, fromEnd: true))]
var slice3 = array[2..];      // array[Range.StartAt(2)]
var slice4 = array[..];       // array[Range.All]

你可以使用范围来代替众所周知的LINQ函数:Skip(), Take(), Count()。