可以向两个方向增长的数组/列表?
Posted
技术标签:
【中文标题】可以向两个方向增长的数组/列表?【英文标题】:Array/List that can Grow in two directions? 【发布时间】:2021-10-23 17:54:40 【问题描述】:好的,这是我的目标:
一个数组,我可以在末尾扩展而不会弄乱索引 即使我想添加一个新对象,在索引 3 处输入的对象也应保留在索引 3 处 在位置“-1”(-1 是初始开始位置之前的位置) 数组中可能有空单元格,以后可以填充到目前为止我的想法:
使用带字符串的字典 可能一直在字符串和数字之间解析效率低下 使用偏移量,只是使阵列更大 我认为这会导致创建很多听起来效率很低的数组 也许一些更智能的算法可以增加数组大小(将其加倍/增加 25 而不是 1) 使用两个数组,一个用于正值,一个用于负值 在接近零位时似乎很难使用我需要这个做什么: 我想制作一个游戏,玩家可以扩展基于 2D 网格的世界,并且新放置的瓷砖周围的瓷砖非常重要(dorfromantik 和 Islanders 之间的混合)
【问题讨论】:
“使用带字符串的目录” - 什么?你的意思是Dictionary
?
拥有包含索引的类的属性。从 1,000,000 开始索引。以后/从不担心性能。
“可能一直在字符串和数字之间进行低效解析”是什么意思?
使用List
并使用Add(item)
在末尾附加项目或使用Insert(0, item)
在开头预附加项目怎么样?
嗨。对于这个任务,我认为你应该考虑链表或者双向链表。您可以追加、预先添加,而不必担心性能问题。 en.wikipedia.org/wiki/Doubly_linked_list
【参考方案1】:
这是一个使用字典的简单示例。希望能给大家一些思路
Dictionary<Vector2, object> map = new Dictionary<Vector2, object>();
int mapSize;
void Start()
GenerateMap(8); // 8 = number of rows and columns
UpdateTileValue(new Vector2(0, 0), "Here's my house"); //set the value of a specific tile
ExpandMap(1); //add another layer to the map surface
private void GenerateMap(int size)
mapSize = size;
int lowerBound = Mathf.FloorToInt(mapSize / 2f);
int upperBound = Mathf.CeilToInt(mapSize / 2f);
for (int row = -lowerBound; row < upperBound; row++)
for (int column = -lowerBound; column < upperBound; column++)
Vector2 address = new Vector2(row, column);
if (!map.ContainsKey(address))
map.Add(address, null);
private void UpdateTileValue(Vector2 address, object value)
if (map.ContainsKey(address))
map[address] = value;
private void ExpandMap(int numLayers) => GenerateMap(mapSize + numLayers);
【讨论】:
感谢一堆,我目前正在尝试仅使用带有偏移量的二维数组,但如果数学过于 Spagetti,我可能会回退到这个解决方案 ^^【参考方案2】:我没有对此进行全面测试,也没有实现所有方法,但这里有一种方法:
public class TwoEndedList<T> : IList<T>
private List<T> _natural = new List<T>();
private List<T> _negative = new List<T>();
public T this[int index]
get => index < 0 ? _negative[-index - 1] : _natural[index];
set
if (index < 0)
_negative[-index - 1] = value;
else
_natural[index] = value;
public int Count => _natural.Count + _negative.Count;
public bool IsReadOnly => false;
public void Add(T item)
_natural.Add(item);
public void AddLast(T item)
_natural.Add(item);
public void AddFirst(T item)
_negative.Add(item);
public void Clear()
_natural.Clear();
_negative.Clear();
public bool Contains(T item) => _natural.Contains(item) || _negative.Contains(item);
public void CopyTo(T[] array, int arrayIndex)
throw new NotImplementedException();
public IEnumerator<T> GetEnumerator()
for (var i = _negative.Count - 1; i >= 0; i--)
yield return _negative[i];
for (var i = 0; i < _natural.Count; i++)
yield return _natural[i];
public int IndexOf(T item)
var index = _natural.IndexOf(item);
if (index == -1)
index = -1 - _negative.IndexOf(item);
return index;
public void Insert(int index, T item)
throw new NotImplementedException();
public bool Remove(T item)
throw new NotImplementedException();
public void RemoveAt(int index)
throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
现在你可以这样做了:
var tel = new TwoEndedList<int>();
tel.Add(4);
tel.Add(5);
tel.AddFirst(1);
tel.AddFirst(2);
foreach (var x in tel)
Console.WriteLine(x);
Console.WriteLine(tel[-2]);
Console.WriteLine(tel[-1]);
Console.WriteLine(tel.IndexOf(2));
这给了我:
2
1
4
5
2
1
-2
【讨论】:
是的,这与我使用的 atm 接近,即使您的实现看起来更干净 我也在使用数组,因为对象之间可能存在“空白”以上是关于可以向两个方向增长的数组/列表?的主要内容,如果未能解决你的问题,请参考以下文章