填充数组以避免索引超出数组错误范围的方法

Posted

技术标签:

【中文标题】填充数组以避免索引超出数组错误范围的方法【英文标题】:Way to pad an array to avoid index outside of bounds of array error 【发布时间】:2012-09-24 21:03:03 【问题描述】:

当我查询它时,我希望列表中至少有 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 个项目的解决方案。

【问题讨论】:

你有没有想过只使用List&lt;string&gt; 而不是数组? 您是如何处理它以使您获得索引越界错误? foreach 在这种情况下会不起作用吗? @Prayos 我会再对您的评论进行 10 次投票,但系统不允许。 Kobojunkie,你为什么要使用数组 per se 考虑到我们在 .NET API 中获得的出色集合类型,这看起来确实很有趣。我假设您将一个数组传递给一个执行 183 次的“for”循环?您无法控制此代码? 我们不知道 183 项数组的 OP 要求的原因。切换到List&lt;&gt; 将无法满足此要求,无论它是什么。 【参考方案1】:

我不能说我会推荐这个解决方案,但我不会让它阻止我发布它!不管他们愿不愿意承认,每个人都喜欢 linq 解决方案!

使用 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!),而且很有趣。

【讨论】:

【参考方案2】:

我可能会听从其他人的建议,并使用一个列表。使用“容量”构造函数来提高性能:

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);
//...

最后,这是我开始编写此答案时使用的相当麻烦的想法:您可以将数组包装在保证具有 183 个索引的 IList 实现中(为简洁起见,我省略了大多数接口成员实现):

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(); 
    

确认。

【讨论】:

【参考方案3】:

既然您已声明需要确保有 183 个索引,并且如果没有则需要填充它,我建议使用 List 而不是数组。您可以执行以下操作:

while (extractList.Count < 183)

     extractList.Add(" "); // just add a space

如果您绝对必须返回到数组,您可以使用类似的东西。

【讨论】:

【参考方案4】:

Array 基类实现Resize 方法

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

但是,请记住,调整大小会影响性能,因此此方法仅在您出于某种原因需要数组时才有用。如果你可以切换到一个列表

而且,我假设你这里有一个一维的字符串数组,所以我使用 Length 属性来检查数组中的有效项数。

【讨论】:

以上是关于填充数组以避免索引超出数组错误范围的方法的主要内容,如果未能解决你的问题,请参考以下文章

致命错误:索引超出范围tableview

致命错误:追加数组时数组索引超出范围

致命错误:单击特定单元格进行 segue 时索引超出范围

错误:索引超出了数组的范围。 [复制]

致命错误:数组索引超出范围。刷新时迅速

索引超出范围错误(从文件中读取的数组)