你怎么做呢?给定一个字节数组:
byte[] foo = new byte[4096];
Run Code Online (Sandbox Code Playgroud)
如何将数组的前x个字节作为单独的数组?(具体来说,我需要它作为一个IEnumerable<byte>)
这是为了与Sockets合作.我认为最简单的方法是数组切片,类似于Perls语法:
@bar = @foo[0..40];
Run Code Online (Sandbox Code Playgroud)
这会将前41个元素返回到@bar数组中.C#中有些东西我只是缺少,还是还有其他一些我应该做的事情?
LINQ对我来说是一个选项(.NET 3.5),如果这有帮助的话.
Mik*_*ott 202
你可以用ArraySegment<T>.它的重量非常轻,因为它不会复制数组:
string[] a = { "one", "two", "three", "four", "five" };
var segment = new ArraySegment<string>( a, 1, 2 );
Run Code Online (Sandbox Code Playgroud)
peS*_*HIr 186
数组是可枚举的,所以你foo已经是一个IEnumerable<byte>本身.只需使用LINQ序列方法Take()就可以得到你想要的东西(不要忘记包含Linq命名空间 using System.Linq;):
byte[] foo = new byte[4096];
var bar = foo.Take(41);
Run Code Online (Sandbox Code Playgroud)
如果你真的需要任何IEnumerable<byte>值的数组,你可以使用这个ToArray()方法.这似乎不是这种情况.
Arj*_*nbu 130
您可以使用数组CopyTo()方法.
或者使用LINQ,您可以使用Skip()和Take()...
byte[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
var subset = arr.Skip(2).Take(2);
Run Code Online (Sandbox Code Playgroud)
WOP*_*OPR 52
static byte[] SliceMe(byte[] source, int length)
{
byte[] destfoo = new byte[length];
Array.Copy(source, 0, destfoo, 0, length);
return destfoo;
}
Run Code Online (Sandbox Code Playgroud)
//
var myslice = SliceMe(sourcearray,41);
Run Code Online (Sandbox Code Playgroud)
Rem*_*_rm 19
从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 }
Run Code Online (Sandbox Code Playgroud)
上面的代码示例摘自C#8.0 博客。
请注意,^前缀表示从数组末尾开始计数。如docs示例所示
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
Run Code Online (Sandbox Code Playgroud)
Range并且Index还可以在切片数组之外工作,例如使用循环
Range range = 1..4;
foreach (var name in names[range])
Run Code Online (Sandbox Code Playgroud)
将遍历条目1至4
请注意,在编写此答案时,C#8.0尚未正式发布
Ken*_*ith 16
我在这里没有提到的另一种可能性:Buffer.BlockCopy()比Array.Copy()略快,它还具有能够从原始数组中即时转换的好处(比如说,简短) [])到一个字节数组,当你需要通过套接字传输数字数组时,它可以很方便.
Pat*_*man 16
在C#7.2中,您可以使用Span<T>.新System.Memory系统的好处是它不需要复制数据.
你需要的方法是Slice:
Span<byte> slice = foo.Slice(0, 40);
Run Code Online (Sandbox Code Playgroud)
很多方法现在支持Span和IReadOnlySpan,所以这将是非常简单的使用这个新的类型.
请注意,在编写本文时,Span<T>尚未在最新版本的.NET(4.7.1)中定义类型,因此要使用它,您需要从NuGet 安装System.Memory包.
Vla*_*vic 14
这是一个简单的扩展方法,它将切片作为新数组返回:
public static T[] Slice<T>(this T[] arr, uint indexFrom, uint indexTo) {
if (indexFrom > indexTo) {
throw new ArgumentOutOfRangeException("indexFrom is bigger than indexTo!");
}
uint length = indexTo - indexFrom;
T[] result = new T[length];
Array.Copy(arr, indexFrom, result, 0, length);
return result;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以用它作为:
byte[] slice = foo.Slice(0, 40);
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 13
如果你想IEnumerable<byte>,那就是
IEnumerable<byte> data = foo.Take(x);
Run Code Online (Sandbox Code Playgroud)
C# 8 现在(自 2019 年起)支持Ranges,这使您可以更轻松地实现 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]
Run Code Online (Sandbox Code Playgroud)
您可以使用范围代替众所周知的 LINQ 函数:Skip()、Take()、Count()。
如果您不想添加LINQ或其他扩展,请执行以下操作:
float[] subArray = new List<float>(myArray).GetRange(0, 8).ToArray();
Run Code Online (Sandbox Code Playgroud)
您可以在原始数组(IList)周围使用包装器,就像在这个(未经测试的)代码段中一样.
public class SubList<T> : IList<T>
{
#region Fields
private readonly int startIndex;
private readonly int endIndex;
private readonly int count;
private readonly IList<T> source;
#endregion
public SubList(IList<T> source, int startIndex, int count)
{
this.source = source;
this.startIndex = startIndex;
this.count = count;
this.endIndex = this.startIndex + this.count - 1;
}
#region IList<T> Members
public int IndexOf(T item)
{
if (item != null)
{
for (int i = this.startIndex; i <= this.endIndex; i++)
{
if (item.Equals(this.source[i]))
return i;
}
}
else
{
for (int i = this.startIndex; i <= this.endIndex; i++)
{
if (this.source[i] == null)
return i;
}
}
return -1;
}
public void Insert(int index, T item)
{
throw new NotSupportedException();
}
public void RemoveAt(int index)
{
throw new NotSupportedException();
}
public T this[int index]
{
get
{
if (index >= 0 && index < this.count)
return this.source[index + this.startIndex];
else
throw new IndexOutOfRangeException("index");
}
set
{
if (index >= 0 && index < this.count)
this.source[index + this.startIndex] = value;
else
throw new IndexOutOfRangeException("index");
}
}
#endregion
#region ICollection<T> Members
public void Add(T item)
{
throw new NotSupportedException();
}
public void Clear()
{
throw new NotSupportedException();
}
public bool Contains(T item)
{
return this.IndexOf(item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex)
{
for (int i=0; i<this.count; i++)
{
array[arrayIndex + i] = this.source[i + this.startIndex];
}
}
public int Count
{
get { return this.count; }
}
public bool IsReadOnly
{
get { return true; }
}
public bool Remove(T item)
{
throw new NotSupportedException();
}
#endregion
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
for (int i = this.startIndex; i < this.endIndex; i++)
{
yield return this.source[i];
}
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
Run Code Online (Sandbox Code Playgroud)
}
小智 6
byte[] foo = new byte[4096];
byte[] bar = foo.Take(40).ToArray();
Run Code Online (Sandbox Code Playgroud)
您可以使用Take扩展方法
var array = new byte[] {1, 2, 3, 4};
var firstTwoItems = array.Take(2);
Run Code Online (Sandbox Code Playgroud)