无法在嵌套字典中存储值

时间:2013-11-04 07:37:46

标签: c# dictionary

我正在尝试将用户的电影评分存储在字典中。获取数据的文件格式为

  

UserID | MovieID |评级|时间戳

它们是制表符分隔值

        //Take the first 100 lines from the file and store each line as a array element of text 
        string[] text = System.IO.File.ReadLines(@File path).Take(100).ToArray();

        //extDic[username] - [moviename][rating] is the structure

        Dictionary<string,Dictionary<string,double>> extDic=new Dictionary<string,Dictionary<string,double>>();
        Dictionary<string, double> movie=new Dictionary<string,double>();
        foreach(string s in text)
        {
            int rating;
            string username=s.Split('\t')[0];
            string moviename=s.Split('\t')[1];
            Int32.TryParse(s.Split('\t')[2], out rating);
            movie.Add(moviename,rating);
            if (extDic.ContainsKey(username))
            {   
                //Error line
                extDic[username].Add(moviename, rating);
            }
            else
            {
                extDic.Add(username, movie);
            }
            movie.Clear();
        }

我在错误行上收到以下错误“已添加了具有相同密钥的项目”。我理解错误是什么,并试图通过检查if语句来解决它。然而,这并没有解决它。

另外,我想知道是否有重要的movie.clear()?

3 个答案:

答案 0 :(得分:3)

必须有该用户和电影的重复。

要修复错误,您可以将其用于“错误行”:

extDic[username][moviename] = rating;

虽然可能还有其他问题。

答案 1 :(得分:1)

问题可能是因为您使用变量movie作为extDic字典中所有条目的值。 movie只是一个参考,因此当您执行movie.Clear()时,您将清除extDic中的所有值。

您可以完全删除变量movie并将其替换为new Dictionary<string, double>()的新实例

string[] text = System.IO.File.ReadLines(@File path).Take(100).ToArray();

//extDic[username] - [moviename][rating] is the structure

Dictionary<string,Dictionary<string,double>> extDic=new Dictionary<string,Dictionary<string,double>>();   
foreach(string s in text)
{
  int rating;
   //split only once
   string[] splitted = s.Split('\t');

  //UPDATE: skip the current line if the structure is not ok
  if(splitted.Length != 3){
      continue;
  }

  string username=splitted[0];
  string moviename=splitted[1];
  Int32.TryParse(splitted[2], out rating);

  //UPDATE: skip the current line if the user name or movie name is not valid
  if(string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(moviename)){
      continue;
  }


   if(!extDic.ContainsKey(username)){
      //create a new Dictionary for every new user
      extDic.Add(username, new Dictionary<string,double>());
   }
   //at this point we are sure to have all the keys set up
   //let's assign the movie rating
   extDic[username][moviename] = rating;

}

答案 2 :(得分:1)

您的问题是您要向所有用户添加相同的字典,因此当两位用户评价同一部电影时,您会看到此异常

int rating;
var result  = from line in text
              let tokens = s.Split('\t')
              let username=tokens[0];
              let moviename=tokens[1];
              where Int32.TryParse(tokens[2], out rating);
              group new {username, Rating=new{moviename,rating}} by username;

上面的代码将为您提供一个从树的角度来看与您自己类似的结构。如果您需要查找功能,只需拨打.ToDictionary

即可
var extDic = result.ToDictionary(x=x.Key, x=>x.ToDictonary(y=>y.moviename,y=>y.rating))

我之所以将其重写为LINQ,是因为使用像LINQ

这样的副作用来解决这些错误是很困难的。