Comment faites-vous? Étant donné un tableau d'octets:
byte[] foo = new byte[4096];
Comment pourrais-je obtenir les x premiers octets du tableau sous forme de tableau séparé? (Plus précisément, j'en ai besoin comme IEnumerable<byte>
)
Ceci est pour travailler avec Socket
s. Je pense que le moyen le plus simple serait le découpage en tableau, similaire à la syntaxe Perls:
@bar = @foo[0..40];
Ce qui renverrait les 41 premiers éléments dans le tableau @bar
. Y-a-t-il quelque chose dans C # qui me manque, ou y a-t-il autre chose que je devrais faire?
LINQ est une option pour moi (.NET 3.5), si cela peut vous aider.
Les tableaux étant énumérables, votre foo
est déjà un IEnumerable<byte>
lui-même. Utilisez simplement les méthodes de séquence LINQ telles que Take()
pour obtenir ce que vous voulez en sortir (n'oubliez pas d'inclure l'espace de noms Linq
avec using System.Linq;
):
byte[] foo = new byte[4096];
var bar = foo.Take(41);
Si vous avez réellement besoin d'un tableau à partir de n'importe quelle valeur IEnumerable<byte>
, vous pouvez utiliser la méthode ToArray()
pour cela. Cela ne semble pas être le cas ici.
Vous pouvez utiliser ArraySegment<T>
. Il est très léger car il ne copie pas le tableau:
_string[] a = { "one", "two", "three", "four", "five" };
var segment = new ArraySegment<string>( a, 1, 2 );
_
Vous pouvez utiliser la méthode arrays CopyTo()
.
Ou avec LINQ, vous pouvez utiliser Skip()
et Take()
...
byte[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
var subset = arr.Skip(2).Take(2);
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);
Une autre possibilité que je n’ai pas vue mentionnée ici: Buffer.BlockCopy () est légèrement plus rapide que Array.Copy () et présente l’avantage supplémentaire de pouvoir convertir à la volée à partir d’un tableau de primitives (disons []) en un tableau d'octets, ce qui peut être pratique lorsque vous devez transmettre des tableaux numériques sur Sockets.
Dans C # 7.2 , vous pouvez utiliser Span<T>
. L'avantage du nouveau système System.Memory
est qu'il n'a pas besoin de copier les données.
La méthode dont vous avez besoin est Slice
:
_Span<byte> slice = foo.Slice(0, 40);
_
Beaucoup de méthodes supportent maintenant Span
et IReadOnlySpan
, il sera donc très simple d'utiliser ce nouveau type.
Notez qu'au moment de l'écriture, le type _Span<T>
_ n'est pas défini dans la version la plus récente de .NET (4.7.1). Pour l'utiliser, vous devez donc installer le . Package System.Memory de NuGet.
À partir de C # 8.0
Le découpage en matrice sera pris en charge, ainsi que les nouveaux types Index
et Range
ajoutés.
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 }
le préfixe ^
indique le décompte à partir de la fin du tableau.
Échantillon de code ci-dessus tiré du C # 8.0 blog .
Range
et Index
fonctionnent également avec des boucles foreach
Range range = 1..4;
foreach (var name in names[range])
Va parcourir les entrées 1 à 4
notez qu'au moment de la rédaction de cette réponse, C # 8.0 n'est pas encore officiellement publié.
Voici une méthode d'extension simple qui renvoie une tranche sous la forme d'un nouveau tableau:
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;
}
Ensuite, vous pouvez l'utiliser comme:
byte[] slice = foo.Slice(0, 40);
Si vous voulez IEnumerable<byte>
, alors
IEnumerable<byte> data = foo.Take(x);
Si vous ne voulez pas ajouter LINQ ou d'autres extensions, faites simplement:
float[] subArray = new List<float>(myArray).GetRange(0, 8).ToArray();
Vous pouvez utiliser un wrapper autour du tableau d'origine (IList), comme dans ce morceau de code (non testé).
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
}
byte[] foo = new byte[4096];
byte[] bar = foo.Take(40).ToArray();
Pour les tableaux d'octets System.Buffer.BlockCopy vous donnera les meilleures performances.
Vous pouvez utiliser la méthode d'extension Take
var array = new byte[] {1, 2, 3, 4};
var firstTwoItems = array.Take(2);
Cela peut être une solution qui:
var result = foo.Slice(40, int.MaxValue);
Alors le résultat est un IEnumerable <IEnumerable <byte >> avec un premier IEnumerable <byte> contient les 40 premiers octets de foo, et un second IEnumerable <byte> conserve le reste.
J'ai écrit une classe de wrapper, l'itération entière est paresseuse, j'espère que cela pourrait aider:
public static class CollectionSlicer
{
public static IEnumerable<IEnumerable<T>> Slice<T>(this IEnumerable<T> source, params int[] steps)
{
if (!steps.Any(step => step != 0))
{
throw new InvalidOperationException("Can't slice a collection with step length 0.");
}
return new Slicer<T>(source.GetEnumerator(), steps).Slice();
}
}
public sealed class Slicer<T>
{
public Slicer(IEnumerator<T> iterator, int[] steps)
{
_iterator = iterator;
_steps = steps;
_index = 0;
_currentStep = 0;
_isHasNext = true;
}
public int Index
{
get { return _index; }
}
public IEnumerable<IEnumerable<T>> Slice()
{
var length = _steps.Length;
var index = 1;
var step = 0;
for (var i = 0; _isHasNext; ++i)
{
if (i < length)
{
step = _steps[i];
_currentStep = step - 1;
}
while (_index < index && _isHasNext)
{
_isHasNext = MoveNext();
}
if (_isHasNext)
{
yield return SliceInternal();
index += step;
}
}
}
private IEnumerable<T> SliceInternal()
{
if (_currentStep == -1) yield break;
yield return _iterator.Current;
for (var count = 0; count < _currentStep && _isHasNext; ++count)
{
_isHasNext = MoveNext();
if (_isHasNext)
{
yield return _iterator.Current;
}
}
}
private bool MoveNext()
{
++_index;
return _iterator.MoveNext();
}
private readonly IEnumerator<T> _iterator;
private readonly int[] _steps;
private volatile bool _isHasNext;
private volatile int _currentStep;
private volatile int _index;
}
Je ne pense pas que C # supporte la sémantique de Range. Vous pouvez cependant écrire une méthode d'extension, comme:
public static IEnumerator<Byte> Range(this byte[] array, int start, int end);
Mais comme d’autres l’ont dit, si vous n’avez pas besoin de définir un index de départ, alors Take
est tout ce dont vous avez besoin.
Voici une fonction d'extension qui utilise un générique et se comporte comme la fonction PHP array_slice . Le décalage négatif et la longueur sont autorisés.
public static class Extensions
{
public static T[] Slice<T>(this T[] arr, int offset, int length)
{
int start, end;
// Determine start index, handling negative offset.
if (offset < 0)
start = arr.Length + offset;
else
start = offset;
// Clamp start index to the bounds of the input array.
if (start < 0)
start = 0;
else if (start > arr.Length)
start = arr.Length;
// Determine end index, handling negative length.
if (length < 0)
end = arr.Length + length;
else
end = start + length;
// Clamp end index to the bounds of the input array.
if (end < 0)
end = 0;
if (end > arr.Length)
end = arr.Length;
// Get the array slice.
int len = end - start;
T[] result = new T[len];
for (int i = 0; i < len; i++)
{
result[i] = arr[start + i];
}
return result;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace data_seniens
{
class Program
{
static void Main(string[] args)
{
//new list
float [] x=new float[]{11.25f,18.0f,20.0f,10.75f,9.50f, 11.25f, 18.0f, 20.0f, 10.75f, 9.50f };
//variable
float eat_sleep_area=x[1]+x[3];
//print
foreach (var VARIABLE in x)
{
if (VARIABLE < x[7])
{
Console.WriteLine(VARIABLE);
}
}
//keep app run
Console.ReadLine();
}
}
}