巨大数据集的数据结构

时间:2014-01-22 10:09:21

标签: c# data-structures collections dataset

我需要为一个类创建一个高效的数据结构,该类存储大小从50,000到100,000的值的Collection。

class TypeData
{
    public string Name { get; set; }
    public Collection<double> Data{ get; set; }
}

现在,用户想要对此数据执行某些操作,然后操作将集合中的实际值替换为“0”。例如

Before operation:
3.4
5.6
66.71
101.44
3.567
345.09

After operation:
3.4
0.0
0.0
101.44
0.0
345.09

现在,用户想要恢复该操作。然后我必须删除所有0.0并且必须将原始值放在集合中的那些索引上。

问题1: 如何跟踪更改的索引?我是否需要保留包含所有已更改索引的另一个列表? 问题2: 如何改进这个类的数据结构,以便它可以容纳数千个实例,即

List<TypeData> dataList = new List<TypeData>(); //此列表的大小可以增长到5000

2 个答案:

答案 0 :(得分:1)

如果您只需要撤消操作一次,那么保留Tim Schmelter的有效/实际值的解决方案是正确的。

如果您需要多个撤消,则必须实施历史记录。同样,您也可以提供 redo 的可能性。

通过一些假设撤消实际上非常容易。如果未更改撤消之间列表中的项目数,则可以将所有更改保存在历史记录(基本上是另一个列表)indexvalue中。撤消操作将遍历历史记录,获取索引并恢复该值。

如果项目数量将被更改,那么最简单的方法是通过制作副本来保存完整的数据。但是,这是耗费内存的操作,但如果您考虑使用数据库或文件来保存这些状态,仍然可以实现。

其他解决方案是实施操作,您可以将其保存在历史记录中。您仍然需要保存状态,但它只是那个大小,需要操作(例如,如果删除项目,则不需要存储整个列表,只删除项目的索引和值)。在这种情况下,撤消将看起来像是从历史记录上一次操作中读取并向后执行(或者您可以从启动开始倒置历史记录,准备撤消,例如,在删除项目的情况下,您可以保存插入操作)。在列表操作的情况下,可能的操作的基本列表可以是:清除,插入,删除,更改值。

答案 1 :(得分:0)

  

问题1:如何跟踪已更改的索引?我需要保持一个   另一个包含所有已更改索引的列表?

我不会存储Collection<double>而是Collection<CustomType>存储值,临时状态和历史记录(如果有的话)。

例如:

public class TypeData
{
    public string Name { get; set; }
    public List<Data> Data { get; set; }
}

public class Data
{
    public enum State
    {
        Unassigned,
        Original,
        Modified
    }

    private double _Value = 0.0d;
    public double Value
    {
        get { return _Value; }
        set
        {
            if (CurrentState == State.Unassigned)
                CurrentState = State.Original;
            else
                CurrentState = State.Modified;
            _Value = value;
            _ValueHistory.Add(value);
            if (_ValueHistory.Count > MaxHistoryCount)
                ClearValueHistory();
        }
    }

    private List<double> _ValueHistory = new List<double> { 0.0d };
    private List<double> ValueHistory
    {
        get { return _ValueHistory; }
        set { _ValueHistory = value; }
    }

    private int _MaxHistoryCount = int.MaxValue;
    public int MaxHistoryCount
    {
        get { return _MaxHistoryCount; }
        set { _MaxHistoryCount = value; }
    }

    public void ClearValueHistory()
    {
        if (_ValueHistory.Count > 1)
            _ValueHistory.RemoveRange(0, _ValueHistory.Count - 1); // keep last
    }

    private State _CurrentState = State.Unassigned;
    public State CurrentState
    {
        get { return _CurrentState; }
        private set { _CurrentState = value; }
    }

    public void RevertOperation(int numRevertCount = 1)
    {
        int newRevisionIndex = _ValueHistory.Count - 1 - numRevertCount;
        if (newRevisionIndex < 0) newRevisionIndex = 0;
        double val = _ValueHistory[newRevisionIndex];
        _ValueHistory.RemoveRange(newRevisionIndex + 1, _ValueHistory.Count - 1 - newRevisionIndex);
        this._Value = val;
    }

    public override string ToString()
    {
        return Value.ToString();
    }
}

以下是样本数据和示例性反向操作:

var listOfData = new List<TypeData>{ 
    new TypeData {
        Name = "TestData",
        Data = new List<Data> 
        {
            new Data { Value = 1.5 }, new Data { Value = 2.4 }, new Data { Value = 1.2 },  new Data(),
            new Data { Value = 0.7 }, new Data { Value = -4.7 }, new Data { Value = 0.0 }, new Data { Value = 4711}
        }
    }
};

foreach (var td in listOfData)
{
    foreach (var data in td.Data.Take(10))
    {
        data.Value = 4711.4711;
    }
}
foreach (var td in listOfData)
{
    foreach (var data in td.Data.Take(10))
    {
        data.RevertOperation();
    }
}
  

问题2:如何改进这个类的数据结构   可容纳数千个实例,即

为什么需要改进它?我会保持原样。我怀疑它需要太多的记忆。否则你应该决定是否购买更多内存,或者你应该使用数据库。