Способ прокладывать массив, чтобы избежать индекса вне границ ошибки массива

StackOverflow https://stackoverflow.com//questions/12716897

Вопрос

Я ожидаю, что в моем списке по меньшей мере 183 наименования, когда я его запрашиваю, но иногда результат от моего извлечения приводит к подсчетам пунктов ниже 183. Мои текущие исправления предположительно прокладывают массив в том случае, если счет меньше, чем183.

if (extractArray.Count() < 183) {
    int arraysize= extractArray.Count();
    var tempArr = new String[183 - arraysize];
    List<string> itemsList = extractArray.ToList<string>();
    itemsList.AddRange(tempArr);
    var values = itemsList.ToArray();
    //-- Process the new array that is now at least 183 in length
}
.

Но кажется, что мое решение не самое лучшее.Я был бы признателен за любые другие решения, которые могли бы помочь, чтобы я получаю не менее 183 предметов, когда экстракт происходит, пожалуйста.

Это было полезно?

Решение

Базовый класс массива реализует Изменение изменений P >.

if(extractArray.Length < 183)
    Array.Resize<string>(ref extractArray, 183);
.

Однако имейте в виду, что изменение изменений проблематично для производительности, поэтому этот метод полезен только в том случае, если вам требуется массив по какой-то причине.Если вы можете переключиться в список

И, я предполагаю, что у вас есть неодимерный массив строк здесь, поэтому я использую свойство длины для проверки эффективного количества элементов в массиве.

Другие советы

Я, наверное, следил за другими предложениями и использую список.Используйте конструктор «Емкость» для добавленной производительности:

var list = new List<string>(183);
.

Тогда, когда вы получаете новый массив, сделайте это (заменить «» любым значением, которое вы используете для прокладки массива):

list.Clear();
list.AddRange(array);
// logically, you can do this without the if, but it saves an object allocation when the array is full
if (array.Length < 183)
    list.AddRange(Enumerable.Repeat(" ", 183 - array.Length));
.

Таким образом, список всегда использует тот же внутренний массив, уменьшая распределение и давление GC.

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

public static class ArrayExtensions
{
    public static T ElementOrDefault<T>(this T[] array, int index)
    {
        return ElementOrDefault(array, index, default(T));
    }
    public static T ElementOrDefault<T>(this T[] array, int index, T defaultValue)
    {
        return index < array.Length ? array[index] : defaultValue;
    }
}
.

Тогда код так:

items.Zero = array[0];
items.One = array[1];
//...
.

становится этим:

items.Zero = array.ElementOrDefault(0);
items.One = array.ElementOrDefault(1);
//...
.

Наконец, это довольно громоздкое представление, с которой я начал писать этот ответ: вы можете обернуть массив в реализации Ilist, которая гарантированно имеет 183 индексов (я пропущен большую часть реализаций интерфейса для краткости): .

class ConstantSizeReadOnlyArrayWrapper<T> : IList<T>
{
    private readonly T[] _array;
    private readonly int _constantSize;
    private readonly T _padValue;

    public ConstantSizeReadOnlyArrayWrapper(T[] array, int constantSize, T padValue)
    {
         //parameter validation omitted for brevity
        _array = array;
        _constantSize = constantSize;
        _padValue = padValue;
    }

    private int MissingItemCount
    {
        get { return _constantSize - _array.Length; }
    }

    public IEnumerator<T> GetEnumerator()
    {
        //maybe you don't need to implement this, or maybe just returning _array.GetEnumerator() would suffice.
        return _array.Concat(Enumerable.Repeat(_padValue, MissingItemCount)).GetEnumerator();
    }

    public int Count
    {
        get { return _constantSize; }
    }

    public bool IsReadOnly
    {
        get { return true; }
    }

    public int IndexOf(T item)
    {
        var arrayIndex = Array.IndexOf(_array, item);
        if (arrayIndex < 0 && item.Equals(_padValue))
            return _array.Length;
        return arrayIndex;
    }

    public T this[int index]
    {
        get
        {
            if (index < 0 || index >= _constantSize)
                throw new IndexOutOfRangeException();
            return index < _array.Length ? _array[index] : _padValue;
        }
        set { throw new NotSupportedException(); }
    }
}
.

ACK.

Поскольку вы заявили, что вам нужно обеспечить 183 индексов, и что вам нужно прокладывать его, если нет, я бы предложил использовать список вместо массива.Вы можете сделать что-то вроде:

while (extractList.Count < 183)
{
     extractList.Add(" "); // just add a space
}
.

Если вы абсолютно должны вернуться к массиву, вы можете использовать что-то похожее.

Я не могу сказать, что я бы порекомендовал это решение, но я не позволю этому останавливать меня от публикации!Хотеят ли они признать это или нет, все лайки BINQ Solutions!

Использование LINQ, учитывая массив с элементами x в нем, вы можете генерировать массив с именно y (183 в вашем случае) элементах в этом, как это:

  var items183exactly = extractArray.Length == 183 ? extractArray :
                        extractArray.Take(183)
                                    .Concat(Enumerable.Repeat(string.Empty, Math.Max(0, 183 - extractArray.Length)))
                                    .ToArray();
.

Если есть менее 183 элементов, массив будет дополнен пустыми строками.Если есть более 183 элементов, массив будет усечен.Если имеется ровно 183 элементов, массив используется как есть.

Я не утверждаю, что это эффективно или что это обязательно хорошая идея.Тем не менее, это использует LINQ (Yippee!) И это весело.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top