C#中的数组切片
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/406485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Array slices in C#
提问by Matthew Scharley
How do you do it? Given a byte array:
你怎么做呢?给定一个字节数组:
byte[] foo = new byte[4096];
How would I get the first x bytes of the array as a separate array? (Specifically, I need it as an IEnumerable<byte>
)
我如何将数组的前 x 个字节作为一个单独的数组?(具体来说,我需要它作为IEnumerable<byte>
)
This is for working with Socket
s. I figure the easiest way would be array slicing, similar to Perls syntax:
这是为了与Socket
s一起工作。我认为最简单的方法是数组切片,类似于 Perls 语法:
@bar = @foo[0..40];
Which would return the first 41 elements into the @bar
array. Is there something in C# that I'm just missing, or is there some other thing I should be doing?
这会将前 41 个元素返回到@bar
数组中。C# 中是否有我遗漏的东西,或者我应该做些什么?
LINQ is an option for me (.NET 3.5), if that helps any.
LINQ 对我来说是一个选项(.NET 3.5),如果有帮助的话。
采纳答案by peSHIr
Arrays are enumerable, so your foo
already is an IEnumerable<byte>
itself.
Simply use LINQ sequence methods like Take()
to get what you want out of it (don't forget to include the Linq
namespace with using System.Linq;
):
数组是可枚举的,所以你foo
已经是一个IEnumerable<byte>
本身。只需使用 LINQ 序列方法,例如Take()
从中获取您想要的内容(不要忘记使用 包含Linq
命名空间 using System.Linq;
):
byte[] foo = new byte[4096];
var bar = foo.Take(41);
If you really need an array from any IEnumerable<byte>
value, you could use the ToArray()
method for that. That does not seem to be the case here.
如果您确实需要来自任何IEnumerable<byte>
值的数组,则可以使用该ToArray()
方法。这里似乎并非如此。
回答by Arjan Einbu
回答by bleevo
I do not think C# supports the Range semantics. You could write an extension method though, like:
我认为 C# 不支持 Range 语义。不过,您可以编写一个扩展方法,例如:
public static IEnumerator<Byte> Range(this byte[] array, int start, int end);
But like others have said if you do not need to set a start index then Take
is all you need.
但是就像其他人所说的那样,如果您不需要设置开始索引,那么Take
您所需要的就是全部。
回答by Marc Gravell
If you want IEnumerable<byte>
, then just
如果你愿意IEnumerable<byte>
,那么就
IEnumerable<byte> data = foo.Take(x);
回答by aku
You can use Take extension method
您可以使用 Take 扩展方法
var array = new byte[] {1, 2, 3, 4};
var firstTwoItems = array.Take(2);
回答by Rauhotz
You could use a wrapper around the original array (which is IList), like in this (untested) piece of code.
您可以在原始数组(即 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
}
}
回答by WOPR
static byte[] SliceMe(byte[] source, int length)
{
byte[] destfoo = new byte[length];
Array.Copy(source, 0, destfoo, 0, length);
return destfoo;
}
//
//
var myslice = SliceMe(sourcearray,41);
回答by Mike Scott
You could use ArraySegment<T>
. It's very light-weight as it doesn't copy the array:
你可以使用ArraySegment<T>
. 它非常轻量级,因为它不复制数组:
string[] a = { "one", "two", "three", "four", "five" };
var segment = new ArraySegment<string>( a, 1, 2 );
回答by Ken Smith
Another possibility I haven't seen mentioned here: Buffer.BlockCopy() is slightly faster than Array.Copy(), and it has the added benefit of being able to convert on-the-fly from an array of primitives (say, short[]) to an array of bytes, which can be handy when you've got numeric arrays that you need to transmit over Sockets.
我在这里没有提到的另一种可能性:Buffer.BlockCopy() 比 Array.Copy() 稍快,并且它具有额外的好处,即能够从一组原语(例如,短[]) 到字节数组,当您有需要通过套接字传输的数字数组时,这会很方便。
回答by greyline
byte[] foo = new byte[4096];
byte[] bar = foo.Take(40).ToArray();