Массив ломтиков в C # - PullRequest
197 голосов
/ 02 января 2009

Как ты это делаешь? Дан байтовый массив:

byte[] foo = new byte[4096];

Как получить первые байты массива в виде отдельного массива? (В частности, мне нужно это как IEnumerable<byte>)

Это для работы с Socket с. Я полагаю, что самым простым способом было бы нарезать массив, аналогично синтаксису Perls:

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

Что вернет первые 41 элемент в массив @bar. Есть ли в C # что-то, чего мне просто не хватает, или есть что-то, что я должен делать?

LINQ - вариант для меня (.NET 3.5), если это поможет.

Ответы [ 18 ]

7 голосов
/ 02 января 2009

Вы можете использовать обертку вокруг исходного массива (который является 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

}

6 голосов
/ 21 октября 2010
byte[] foo = new byte[4096]; 

byte[] bar = foo.Take(40).ToArray();
5 голосов
/ 02 января 2009

Вы можете использовать метод расширения Take

var array = new byte[] {1, 2, 3, 4};
var firstTwoItems = array.Take(2);
5 голосов
/ 03 февраля 2016

Для байтовых массивов System.Buffer.BlockCopy обеспечит наилучшую производительность.

3 голосов
/ 05 сентября 2013

Это может быть решение, которое:

var result = foo.Slice(40, int.MaxValue);

Тогда результат будет IEnumerable > с первым IEnumerable содержит первые 40 байтов foo , а второй IEnumerable содержит остаток.

Я написал класс-обертку, вся итерация ленива, надеюсь, это поможет:

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;
}
2 голосов
/ 02 января 2009

Я не думаю, что C # поддерживает семантику Range. Вы можете написать метод расширения, например:

public static IEnumerator<Byte> Range(this byte[] array, int start, int end);

Но, как говорили другие, если вам не нужно устанавливать начальный индекс, тогда Take - это все, что вам нужно.

1 голос
/ 25 октября 2014

Вот функция расширения, которая использует универсальный и ведет себя как функция PHP array_slice . Отрицательное смещение и длина допускаются.

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;
    }
}
0 голосов
/ 19 мая 2019
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();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...