【问题标题】:How to add up all values in dictionary from one key to the next? [closed]如何将字典中的所有值从一个键加到下一个键? [关闭]
【发布时间】:2018-05-27 01:13:52
【问题描述】:

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

【问题讨论】:

  • It should also include the values for the start and ending integers 请解释一下这一行,你没有提到任何关于开始和结束整数的事情。
  • 假设我需要从 2018 年 5 月 26 日到 2018 年 6 月 23 日之间加起来一些东西。它还应在计算中包括这些日期的值。
  • 有什么理由将日期存储为字符串?
  • 不,我是编程新手,不确定最好的方法。我只是认为输入字符串比输入日期时间更容易。

标签: c# dictionary


【解决方案1】:

我的建议是保留 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&lt;T&gt;

你可以这样做,看看这个问题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));

【讨论】:

  • 你能写一些关于dictionary.Where的更多信息吗?我不明白这都是什么意思。
  • @DanielV。更新
  • 你知道如何将 DateTime.Now.Date 输入到方法中吗?当我尝试将其输入为 2018 年 5 月 26 日时,它说它无法将 int 转换为 System.DateTime。
  • @DanielV。 public void MyMethod(DateTime myDate) {..} 用法 MyMethod(DateTime.Now.Date)
  • 你能做这种方法吗(5/26/2018)
【解决方案2】:

我通过没有循环的 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}");
                }
            }
        }

【讨论】:

    【解决方案3】:

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

    我可以感觉到你在 Linq 代码中对此没有什么困惑,所以这里是更简单的代码。

    假设你的字典是Dictionary&lt;string, int&gt; 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&lt;string, int&gt; 并返回该字典。

    调用这个方法,

    dateNumDict = LoadDict();
    

    【讨论】:

      猜你喜欢
      • 2021-03-04
      • 1970-01-01
      • 1970-01-01
      • 2020-01-03
      • 1970-01-01
      • 2019-06-19
      • 2014-01-02
      • 1970-01-01
      相关资源
      最近更新 更多