如何将字典中的所有值从一个键添加到下一个键?

时间:2018-05-27 01:13:53

标签: c# dictionary

我有一个字典,其中DateTime.Now.Date转换为字符串作为键,整数作为值。我需要以某种方式将所有整数从一个输入的密钥加到下一个密钥。它还应包括开始和结束整数的值。我怎么能这样做?另外,我怎么能将这个字典保存到计算机中,这样当我打开程序时会加载相同的字典并继续添加到它?

3 个答案:

答案 0 :(得分:2)

我的建议是让DateTime保持其自然类型,让生活更轻松

你可以做这样的事情

<强>鉴于

public static void Serialize(Dictionary<DateTime, int> dictionary, Stream stream)
{
   var writer = new BinaryWriter(stream);
   writer.Write(dictionary.Count);
   foreach (var kvp in dictionary)
   {
      writer.Write(kvp.Key.ToBinary());
      writer.Write(kvp.Value);
   }

   writer.Flush();
}

public static Dictionary<DateTime, int> Deserialize(Stream stream)
{
   var reader = new BinaryReader(stream);
   var count = reader.ReadInt32();
   var dictionary = new Dictionary<DateTime, int>(count);
   for (var n = 0; n < count; n++)
   {
      var key = DateTime.FromBinary(reader.ReadInt64());
      var value = reader.ReadInt32();
      dictionary.Add(key, value);
   }

   return dictionary;
}

<强>用法

// Create some data
var dictionary = new Dictionary<DateTime, int>();
dictionary.Add(DateTime.Now.AddDays(-10), 34);
dictionary.Add(DateTime.Now.AddDays(-5), 234);
dictionary.Add(DateTime.Now.AddDays(-2), 345);
dictionary.Add(DateTime.Now, 434);

// Example using sum
var sum = dictionary.Where(x => x.Key > DateTime.Now.AddDays(-6) && x.Key < DateTime.Now.AddDays(-1))
            .Sum(x => x.Value);

Console.WriteLine(sum);

// write to file
using (var fileStrem = new FileStream(@"D:\dict.dat", FileMode.Create))
{
   Serialize(dictionary, fileStrem);
}

// Read from file 
using (var fileStrem = new FileStream(@"D:\dict.dat", FileMode.Open))
{
   dictionary = Deserialize(fileStrem);
}

// sanity check
sum = dictionary.Where(x => x.Key > DateTime.Now.AddDays(-6) && x.Key < DateTime.Now.AddDays(-1))
                  .Sum(x => x.Value);


Console.WriteLine(sum);

<强>输出

579
579

<强>更新

Enumerable.Where Method (IEnumerable, Func)

  

根据谓词过滤一系列值。

基本上你可以在字典上使用where子句,因为它基本上只是KeyValuePair Structure

  

定义可以设置或检索的键/值对。

您也可以阅读Linq

Language Integrated Query (LINQ)

<强>更新

  

是否可以使用具有相同键的字典   他们有不同的价值观?

在这种情况下,你最好只使用List<T>

您可以执行此操作,请查看此问题Key Value Pair List

var list = new List<KeyValuePair<DateTime, int>>() 

然后在序列化方法中,只需更改

的所有事件
Dictionary<DateTime, int>

KeyValuePair<DateTime, int> 

List<KeyValuePair<DateTime, int>> 

然后添加

list.Add(new KeyValuePair<DataTime, int>(myDate,ads));

答案 1 :(得分:0)

我用BinaryFormatter Done学习了这个,没有循环,对我来说似乎有点简单。只是保存和检索部分而不是其余部分。

private void SaveAsBinary()
        {
            Dictionary<DateTime, int> myData = new Dictionary<DateTime, int>();
            myData.Add(new DateTime(2018,4,11), 24);
            myData.Add(new DateTime(2017,4,13), 32);
            myData.Add(new DateTime(2016,7,22), 37);
            BinaryFormatter bf = new BinaryFormatter();

            using (Stream fs = new FileStream("myData.dat", FileMode.Create, FileAccess.Write, FileShare.None))
            {
                bf.Serialize(fs, myData);
            }
            MessageBox.Show("Saved Dictionary as binary");
        }
        private void RetrieveDictionay()
        {
            BinaryFormatter bf = new BinaryFormatter();
            using (Stream fs = File.OpenRead("myData.dat"))
            {
                Dictionary<DateTime,int> myDataFromDisk = (Dictionary<DateTime,int>)bf.Deserialize(fs);

                foreach (KeyValuePair<DateTime,int> kv in myDataFromDisk)
                {
                    Debug.Print($"Key = {kv.Key}, Value = {kv.Value}");
                }
            }
        }

答案 2 :(得分:0)

  

我需要以某种方式将所有整数从一个输入的密钥加到下一个密钥。

为了这个目的,我觉得你在Linq代码中几乎没有混淆,所以这里有更简单的代码。

假设您的词典为Dictionary<string, int> dateNumDict

您可以创建如下方法

    int GetSumOfIntBetweenTwoDateString(Dictionary<string, int> dateNumDict, string startKey, string endKey)
    {
        int sum = 0;
        if (dateNumDict.ContainsKey(startKey) && dateNumDict.ContainsKey(endKey))
        {
            List<string> keys = dateNumDict.Keys.ToList();

            int startIndex = keys.IndexOf(startKey);
            int endIndex = keys.IndexOf(endKey);


            for(int i = startIndex; i <= endIndex; i++)
            {
                sum += dateNumDict[keys[i]];
            }
        }
        return sum;
    }

此方法将接受您的字典,启动键和结束键作为输入,并将所有整数从开始键的值加到结束键的值,并返回结果总和。

这也将检查字典中是否存在源键或目标键,并相应地执行任务。

调用此方法将是,

int sum = GetSumOfIntBetweenTwoDateString(dateNumDict, sourceDateKey, destDateKey);

传递字典为passing by reference,您无需担心从此方法中获取更新(输出)字典。

注意如果您的要求就像添加关键日期时间介于开始时间和结束时间之间的所有数据,您必须记住字典中数据的顺序。

对于前。

字典具有类似

的值
        dateNumDict.Add("5/27/2018 12:19:11 PM", 1);
        dateNumDict.Add("5/27/2018 12:29:11 PM", 2);
        dateNumDict.Add("5/27/2018 12:25:11 PM", 3);

如果您在“5/27/2018 12:19:11 PM”到“5/27/2018 12:25:11 PM”之间添加数据,它会将所有三个值相加,按顺序,有这些日期之间的三个条目。

  

另外如何将这本字典保存到电脑中,以便在我打开程序时加载相同的字典

为此您可以使用serialization的概念(有多种方法可以序列化数据,但这里我们将使用二进制序列化)

您可以使用以下方法

    void SaveDict(Dictionary<string, int> dateNumerDict)
    {
        try
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            using (Stream dataStream = new FileStream("Data.dat", FileMode.Create))
            {
                binaryFormatter.Serialize(dataStream, dateNumerDict);
            }
        }
        catch (Exception ex) { /*log exception if you want*/ }
    }

SaveDict方法将接受您的字典作为输入并将其保存到名为“Data.dat”的文件中。

请注意,您需要添加using System.Runtime.Serialization.Formatters.Binary;以使用BinaryFormatterusing System.IO;来使用文件顶部的FileStream相关类。

调用此方法很简单,

SaveDict(dateNumDict);

另一种方法,读取数据将如下所示

    Dictionary<string, int> LoadDict()
    {
        Dictionary<string, int> dateNumDict = new Dictionary<string, int>();
        if(File.Exists("Data.dat"))
        {
            try
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                using (FileStream fileStream = new FileStream("Data.dat", FileMode.Open))
                {
                    dateNumDict = (Dictionary<string, int>)binaryFormatter.Deserialize(fileStream) ;
                }
            }
            catch (Exception ex) { /*log exception if you want*/ }
        }
        return dateNumDict;
    }

此方法将查找文件“Data.dat”。如果它确实存在,它将反序列化它并从中读取Dictionary<string, int>并返回该字典。

调用此方法,

dateNumDict = LoadDict();