可以向两个方向增长的数组/列表?

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 接近,即使您的实现看起来更干净 我也在使用数组,因为对象之间可能存在“空白”

以上是关于可以向两个方向增长的数组/列表?的主要内容,如果未能解决你的问题,请参考以下文章

我可以为升序堆栈增长方向配置 ARM 处理器吗?

所有蚂蚁掉下来前的最后一刻

栈增长方向和数组增长方向

我如何创建两个在不同方向上相互同步的可滚动列表

大端小端系统_union_栈的增长方向

这个控件的名称是啥?两个带有方向栏的可滚动列表