填充数组的方式,以避免索引阵列错误的界限
-
13-12-2019 - |
题
我希望在我的列表中有至少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个项目。
解决方案
阵列基类实现调整大小方法
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个索引(我省略了Brevity的大多数接口成员实现):
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
}
.
如果您绝对必须返回某个数组,您可以使用类似的东西。
我不能说我会推荐这个解决方案,但我不会让它阻止我发布它!他们是否喜欢承认与否,每个人都喜欢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!),它很有趣。
不隶属于 StackOverflow