如何覆盖列表?

7

我需要一个与列表类似的集合,当达到特定长度时,它应该开始从第一个索引覆盖值,并按循环顺序继续。

例如,对于4个项目的限制:

specialList.Add(100); // {100}
specialList.Add(101); // {100, 101}
specialList.Add(102); // {100, 101, 102}
specialList.Add(103); // {100, 101, 102, 103}
specialList.Add(104); // {104, 101, 102, 103}
specialList.Add(105); // {104, 105, 102, 103}

你将如何知道要覆盖哪些值?你可以通过索引引用项目(myList[index] = newValue)并设置新值。 - Alex
你想保留最后10个项目吗?还是清空列表也可以? - S.Serpooshan
@S.Serp 是的,我需要保留最后10个项目。实际上,列表的长度将被限制为10个项目,并且新项目将从开头开始覆盖旧项目。 - user6813020
1
你无法通过标准列表实现那个。实现类似的功能最好的方法是创建一个继承自IList<>接口的自定义列表。 - Pawel Maga
@PawelMaga 我的答案中展示了一个简单的实现。 - S.Serpooshan
如果你真的需要这种类型,请忽略这里的答案并搜索“循环缓冲区”,这就是问题所要求的。 - Alexei Levenkov
2个回答

6

(更新为常规列表类) 这是一个可用于特殊列表类的类,它在到达最后一个元素时循环(循环到第一个项目):

public class ListCycle<T> : IList<T>
{

    int curIndex = -1;
    List<T> list;
    int nMax;

    public ListCycle(int n)
    {
        list = new List<T>(n);
        nMax = n;
    }

    /// <summary>returns the current index we are in the list</summary>
    public int CurIndex { get { return curIndex; } }

    public int IndexOf(T item) { return list.IndexOf(item); }
    public bool Contains(T item) { return list.Contains(item); }
    public int Count { get { return list.Count; } }
    public bool IsReadOnly { get { return false; } }
    public IEnumerator<T> GetEnumerator() { return list.GetEnumerator(); }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return list.GetEnumerator(); }

    public T this[int index]
    {
        get { return list[index]; }
        set { list[index] = value; }
    }

    public void Add(T item)
    {
        curIndex++; if (curIndex >= nMax) curIndex = 0;
        if (curIndex < list.Count)
            list[curIndex] = item;
        else
            list.Add(item);
    }

    public void Clear()
    {
        list.Clear();
        curIndex = -1;
    }

    //other mehods/properties for IList ...
    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(); }
    public void CopyTo(T[] array, int arrayIndex) { throw new NotImplementedException(); }

}

使用方法很简单:

var list = new ListCycle<int>(10);

//fill the list
for (int i = 0; i < 10; i++)
{
    list.Add(i);
}

//now list is:
// 0, 1, 2, 3, ...

//add more items will start from first
list.Add(100); //overrides first item
list.Add(101); //overrides second item

//now list is:
// 100, 101, 2, 3, ...

@S.Serp感谢您的出色回答!我认为很多人会发现它很有用。但是我喜欢Yousaf提供的简单解决方案。 - user6813020
我更新了我的答案来定义一个通用的特殊列表类,这可能更有用。我认为其他用户提供的答案,如myList[0] = (newItem);是显而易见的,实际使用起来不太简单...那样你必须自己跟踪curIndex。 - S.Serpooshan

5

不要直接覆盖list,为什么不清空list后再逐个添加项目。

使用以下方法清空list

myList.Clear();

然后在你的list中添加项目:

myList.add(item);

编辑

如果您想保留旧的值,则在 list 填满 10 个项目后,将新项目添加到第一个索引中,如下所示:

myList[0] = (newItem);  

newItem会覆盖你的list中的第一个项目。


也许他想保留旧值,例如始终保留最后10个项目。 - S.Serpooshan
@Yousaf,谢谢你的回答,但我需要保留列表中的旧值。 - user6813020
@Yousaf,非常感谢,一切都比我想象的要容易。 - user6813020

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接