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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 02:10:20  来源:igfitidea点击:

Array slices in C#

c#arrays

提问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 Sockets. I figure the easiest way would be array slicing, similar to Perls syntax:

这是为了与Sockets一起工作。我认为最简单的方法是数组切片,类似于 Perls 语法:

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

Which would return the first 41 elements into the @bararray. 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 fooalready 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 Linqnamespace 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

You could use the arrays CopyTo()method.

您可以使用数组CopyTo()方法。

Or with LINQ you can use Skip()and Take()...

或者使用 LINQ,您可以使用Skip()Take()...

byte[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
var subset = arr.Skip(2).Take(2);

回答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 Takeis 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();