2013-11-04 25 views
0

我試圖在字典中存儲用戶的電影評級。從中獲取數據的文件格式爲無法將值存儲在嵌套字典中

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()?

回答

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; 

} 
+0

我修改了代碼以添加一些額外的驗證步驟:一個用於解析一行('splitted.Length'應該等於3),另一個用於非null'username'和'moviename' ;這兩個都用作鍵,不應該是空字符串或空值。我希望有所幫助。 – Lucian

3

必須有該用戶和電影的重複。

要修正此錯誤,您可以使用此爲您的「錯誤路線」:

extDic[username][moviename] = rating; 

雖然有可能要發生了其他問題。

+0

副作用失誤這消除了例外,但你確定它修復了錯誤?我無法看到,根據自然法則覆蓋以前存儲的評級是正確的,也許它是或者也許第一個是正確的,或者平均值或者可能它永遠不會發生用戶對相同電影評價兩次 –

+0

@RuneFS,我不確定(因此我的最後一句話)。我沒有他的數據,所以我可以說是否重複。 –

+0

您在自己的評論中確信自己已經修復了錯誤,指出您不知道錯誤是什麼。這是我的觀點 –

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