因此,我已经使用以下代码一段时间了,直到最近它才抛出异常。
// median-of-medians search:
const int MOM_GROUP_SIZE = 5;
List<KeyValuePair<int, float>> mediansList = indexPositionPairs;
while (mediansList.Count > 1) // could be only one because of outer loop, so check before first (inner) iteration!
{
List<KeyValuePair<int, float>> groupMediansList;
int fullGroupListLength = mediansList.Count / MOM_GROUP_SIZE;
int remainderGroupSize = mediansList.Count % MOM_GROUP_SIZE;
if (remainderGroupSize > 0)
{
groupMediansList = new List<KeyValuePair<int, float>>(fullGroupListLength + 1);
// find last group median
int startingIndex = fullGroupListLength * MOM_GROUP_SIZE;
mediansList.Sort(startingIndex, remainderGroupSize, comp);
groupMediansList[fullGroupListLength] = mediansList[startingIndex + remainderGroupSize / 2];
}
else
{
groupMediansList = new List<KeyValuePair<int, float>>(fullGroupListLength);
}
// groups of 5:
for (int i = 0, j = 0; i < fullGroupListLength; ++i, j += MOM_GROUP_SIZE)
{
mediansList.Sort(j, MOM_GROUP_SIZE, comp);
groupMediansList[i] = mediansList[j + MOM_MEDIAN_OFFSET];
}
// repeat on the group medians until only one remains
mediansList = groupMediansList;
}现在,我从下面一行中得到一个ArgumentOutOfRangeException:
groupMediansList[fullGroupListLength] = mediansList[startingIndex + remainderGroupSize / 2];特别是左边,我试图在索引处设置一个值。我收到了异常消息:
“索引超出了范围。必须是非负的,且小于集合的大小。\r\n参数名称: index”
阅读微软的在线文档的一些内容,当index大于或等于Count时,似乎确实应该抛出一个Count。
但是,正如您在代码中进一步看到的那样,我使用相同的方法填充列表,这不会导致异常。我也非常怀疑这个特定的代码块以前从未被调用过,因为它需要所有以前使用的数据集,这些代码的大小都是5的自然幂。
到目前为止,这是我使用过的最大的数据集(1366921元素!),所以这会产生任何效果吗?(理想情况下不应该这样,但你永远不会知道.)
现在,我将使用数组重写它,但我想了解这里发生了什么。我一直认为,如果列表超出了当前的大小,列表中的按索引寻址就会自动扩展列表,我担心这对我以前的项目有什么影响。
发布于 2018-12-19 16:45:13
首先,接受List<T>参数的int构造函数将具有指定容量(而不是长度)的列表初始化。这意味着结果列表的初始Count总是为零。
其次,当您按索引访问元素时,列表不会神奇地增长,只有当您调用Add或Insert (或AddRange或InsertRange时,才会得到gist)。即使它们确实增长了,您仍然不允许访问Count和Capacity之间的任何索引。
我怀疑第二种方法“从未导致异常”,因为这是同一个问题:您正在创建一个具有特定容量的空列表,然后立即尝试访问超出其计数的索引。C#与C++不一样,在这里,这可以归结为未定义的行为:在这里,每次都会抛出。
因为您的算法似乎是“创建一个预定长度的列表,然后替换单个元素”,所以数组可能更适合。
发布于 2018-12-19 16:42:50
groupMediansList = new List<KeyValuePair<int, float>>(fullGroupListLength + 1);看起来,您的工作假设是将列表的容量设置为fullGroupListLength + 1,允许您通过fullGroupListLength访问索引0。然而,容量和计数是两种不同的东西。不能访问大于或等于groupMediansList.Count的索引。解决方案是将所需的值数添加到列表中,或者使用不同的集合,比如数组。
https://stackoverflow.com/questions/53855471
复制相似问题