我非常难过
如何在C#中使用迭代器,就像C ++迭代器一样?我找不到Begin()或End()访问器,我甚至无法找到如何声明迭代器。我读过关于Ienumerator的文章。我的目标是实现合并功能。这是我用C ++编写的Merge函数的一部分。大多数情况下,我正在寻找所显示内容的C#等价物,除了我将使用引用类型而不是整数。
void merge(vector<int>::iterator left, vector<int>::iterator right, vector<int>::iterator leftEnd, vector<int>::iterator rightEnd, vector<int>::iterator full)
{
while(left != leftEnd && right!= rightEnd) //compare left and right until the end of the vector is reached
{
if(*right < *left) //right < left so insert right to the output vector and advance the iterators
{
*full++ = *right++;
}
else //left < right so insert left to the output vector and advance the iterators
{
*full++ = *left++;
}
}
while(left != leftEnd) //copy any remaining elements into the output from left
{
*full++ = *left++;
}
}
另外,我应该使用哪些系列? (目前我一直在尝试List<T>
和LinkedList<T>
)。
答案 0 :(得分:7)
听起来你想要这样的东西:
bool leftValid = left.MoveNext();
bool rightValid = right.MoveNext();
while (leftValid && rightValid)
{
if (right.Current < left.Current)
{
full.Add(right.Current);
rightValid = right.MoveNext();
}
else
{
full.Add(left.Current);
leftValid = left.MoveNext();
}
}
while (leftValid)
{
full.Add(left.Current);
leftValid = left.MoveNext();
}
while (rightValid)
{
full.Add(right.Current);
rightValid = right.MoveNext();
}
这里full
需要某种IList<T>
- .NET迭代器不允许你对底层集合进行更改。
你不应该尝试编写“桥接”代码,以便让你使用像C ++那样的.NET迭代器;当你使用.NET时,尝试用.NET迭代器开始思考会好得多。
请注意,在.NET中传递迭代器是非常罕见的。将方法设置为IEnumerable<T>
参数更自然,并执行以下操作:
using (IEnumerable<T> leftIterator = leftSequence.GetEnumerator())
{
using (IEnumerable<T> rightIterator = rightSequence.GetEnumerator())
{
// Code as above, just using leftIterator and rightIterator
// instead of left and right
}
}
答案 1 :(得分:3)
.net容器不支持C ++样式迭代器。他们唯一拥有的是
IEnumerator<T>
他们唯一可以做的就是在foreach
语句中进行迭代。
您可能希望查看允许随机访问的IList<T>
接口,但仅支持快速索引的集合。在这样的集合上,您可以使用索引实现就地合并排序。
void Merge<T>(IList<T> container,int left, int right, int leftEnd, int rightEnd, int full)
然后使用container[left]
代替*left
。
这样做的不幸后果是,您无法像C ++那样实现有效的就地容器不可知排序功能。
答案 2 :(得分:2)
我想你想要GetEnumerator(),MoveNext()和Current。
通常,您可以使用foreach进行迭代,但您的情况很特殊。
如果事实,而不是使用“完整”,将其组织为迭代器块并懒惰地合并两个枚举。
IEnumerable<T> Merge<T>(IEnumerable<T> left, IEnumerable<T> right)
{
... yield return Min<T>(left.Current, right.Current); ..,
}
答案 3 :(得分:0)
您可以使用具有固定大小或List<T>
的数组,这些数组在其他语言中也称为ArrayLists。他们的项目可以通过索引器(list[i]
)访问,项目可以附加list.Add(item);
。它们会自动增长。 <{1}}无法通过索引器访问,必须遍历。
你会声明像这样的方法
LinkedLists
你可以得到像这样的枚举器
void merge(IEnumerator<int> left, IEnumerator<int> right,
List<int> full)
{
// Jon Skeet's code goes here
}
IEnumerable<int> intEnumerable = ...;
IEnumerator<int> intEnumerator = intEnumerable.GetEnumerator();
由大多数通用集合类型实现。非通用集合通常实现IEnumerable<T>
。
(编辑回应@ CodeInChaos的评论)。