去 i-1 时如何处理循环
How to handle loops when going i-1
我有一个关于在 C# 中循环的一般性问题,尤其是在使用列表时。
我想实现一个简单的多边形切耳算法。
这是算法:
(来源:http://www.diva-portal.org/smash/get/diva2:330344/FULLTEXT02
, 第 6 页)
我已经实现了寻找耳塞。但问题是我必须访问列表的 i-1 或有时甚至是 i-2 元素。我的解决方法是在列表顶部添加最后一个元素,在列表末尾添加第一个元素。
但是当它进入下一步时,当我必须从多边形中删除一些点以通过算法走得更远时,这种方法一点也不好。所以问题是当我在开始工作时尝试访问多边形末端的元素时 =) 我希望这是有道理的。
这里有一个片段,让你知道我在说什么:
// suppose that i = 0 at the first step and polygonPoints is List<Vector>
Vector pi = new Vector(polygonPoints[i - 1]);
Vector pj = new Vector(polygonPoints[i]);
Vector pk = new Vector(polygonPoints[i + 1]);
// create line between i-1 and i+1
Line diagonal = new Line(pi,pk);
如有任何建议,我将不胜感激。
提前致谢。
希望我理解正确:你的问题是计算节点列表末尾的邻居索引,对吗?
如果是这样,您为什么不使用简单的模函数来计算索引:
int mod(int k, int x)
{
return ((k % x) + x) % x;
}
//...
polygonPoints[mod(i + n, polygonPoints.length)]
其中 n
是您的偏移量。
这意味着例如对于包含 10 个元素的多边形点列表,i = 9
和 n = 1
即:
mod((9 + 1), 10) = 0
特别是,索引 9
处节点的下一个邻居位于索引 0
。
对于i = 0
和n = -1
:
mod((0 - 1), 10) = 9
这意味着,索引 0
处节点的前一个节点位于索引位置 9
。
您还可以在集合上创建一个 decorator。
然后你可以定义indexer property来处理越界索引。
这样你就不用一直调用mod
,它会在索引器中处理。您必须有一个支持索引或 IndexOf
的集合,例如 List
.
using System;
using System.Collections;
using System.Collections.Generic;
class Program
{
private static void Main(string[] args)
{
var list = new List<int> { 1, 2, 3, 4, 5 };
var decoratedList = new OverindexableListDecorator<int>(list);
Console.WriteLine("-1st element is: {0}", decoratedList[-1]);
Console.WriteLine("Element at index 3 is: {0}", decoratedList[3]);
Console.WriteLine("6th element is: {0}", decoratedList[6]);
Console.ReadKey();
}
}
class OverindexableListDecorator<T> : IList<T>
{
private readonly IList<T> store;
public OverindexableListDecorator(IList<T> collectionToWrap)
{
this.store = collectionToWrap;
}
public T this[int index]
{
get
{
int actualIndex = IndexModuloCount(index);
return store[actualIndex];
}
set
{
int actualIndex = IndexModuloCount(index);
store[actualIndex] = value;
}
}
public void RemoveAt(int index)
{
var actualIndex = IndexModuloCount(index);
store.RemoveAt(index);
}
public void Insert(int index, T item)
{
var actualIndex = IndexModuloCount(index);
store.Insert(actualIndex, item);
}
private int IndexModuloCount(int i)
{
int count = this.Count;
return ((i % count) + count) % count;
}
#region Delegate calls
public IEnumerator<T> GetEnumerator()
{
return store.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
store.Add(item);
}
public void Clear()
{
store.Clear();
}
public bool Contains(T item)
{
return store.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
store.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
return store.Remove(item);
}
public int Count
{
get { return store.Count; }
}
public bool IsReadOnly
{
get { return store.IsReadOnly; }
}
public int IndexOf(T item)
{
return store.IndexOf(item);
}
#endregion
}
我有一个关于在 C# 中循环的一般性问题,尤其是在使用列表时。
我想实现一个简单的多边形切耳算法。 这是算法:
我已经实现了寻找耳塞。但问题是我必须访问列表的 i-1 或有时甚至是 i-2 元素。我的解决方法是在列表顶部添加最后一个元素,在列表末尾添加第一个元素。
但是当它进入下一步时,当我必须从多边形中删除一些点以通过算法走得更远时,这种方法一点也不好。所以问题是当我在开始工作时尝试访问多边形末端的元素时 =) 我希望这是有道理的。
这里有一个片段,让你知道我在说什么:
// suppose that i = 0 at the first step and polygonPoints is List<Vector>
Vector pi = new Vector(polygonPoints[i - 1]);
Vector pj = new Vector(polygonPoints[i]);
Vector pk = new Vector(polygonPoints[i + 1]);
// create line between i-1 and i+1
Line diagonal = new Line(pi,pk);
如有任何建议,我将不胜感激。 提前致谢。
希望我理解正确:你的问题是计算节点列表末尾的邻居索引,对吗?
如果是这样,您为什么不使用简单的模函数来计算索引:
int mod(int k, int x)
{
return ((k % x) + x) % x;
}
//...
polygonPoints[mod(i + n, polygonPoints.length)]
其中 n
是您的偏移量。
这意味着例如对于包含 10 个元素的多边形点列表,i = 9
和 n = 1
即:
mod((9 + 1), 10) = 0
特别是,索引 9
处节点的下一个邻居位于索引 0
。
对于i = 0
和n = -1
:
mod((0 - 1), 10) = 9
这意味着,索引 0
处节点的前一个节点位于索引位置 9
。
您还可以在集合上创建一个 decorator。 然后你可以定义indexer property来处理越界索引。
这样你就不用一直调用mod
,它会在索引器中处理。您必须有一个支持索引或 IndexOf
的集合,例如 List
.
using System;
using System.Collections;
using System.Collections.Generic;
class Program
{
private static void Main(string[] args)
{
var list = new List<int> { 1, 2, 3, 4, 5 };
var decoratedList = new OverindexableListDecorator<int>(list);
Console.WriteLine("-1st element is: {0}", decoratedList[-1]);
Console.WriteLine("Element at index 3 is: {0}", decoratedList[3]);
Console.WriteLine("6th element is: {0}", decoratedList[6]);
Console.ReadKey();
}
}
class OverindexableListDecorator<T> : IList<T>
{
private readonly IList<T> store;
public OverindexableListDecorator(IList<T> collectionToWrap)
{
this.store = collectionToWrap;
}
public T this[int index]
{
get
{
int actualIndex = IndexModuloCount(index);
return store[actualIndex];
}
set
{
int actualIndex = IndexModuloCount(index);
store[actualIndex] = value;
}
}
public void RemoveAt(int index)
{
var actualIndex = IndexModuloCount(index);
store.RemoveAt(index);
}
public void Insert(int index, T item)
{
var actualIndex = IndexModuloCount(index);
store.Insert(actualIndex, item);
}
private int IndexModuloCount(int i)
{
int count = this.Count;
return ((i % count) + count) % count;
}
#region Delegate calls
public IEnumerator<T> GetEnumerator()
{
return store.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
store.Add(item);
}
public void Clear()
{
store.Clear();
}
public bool Contains(T item)
{
return store.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
store.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
return store.Remove(item);
}
public int Count
{
get { return store.Count; }
}
public bool IsReadOnly
{
get { return store.IsReadOnly; }
}
public int IndexOf(T item)
{
return store.IndexOf(item);
}
#endregion
}