2016-04-13 82 views
1

我有一個Dictionary<string, string>roleList。在這種情況下,roleList列出角色和角色在層次結構上方的作用和角色 - 我需要保留與「鍵」角色匹配的項的鍵和值,並可以丟棄其餘部分。Filter Dictionary <string,string>使用LINQ select

我也可以訪問先前編寫的函數,它可以讓我知道用戶是否在特定角色(或角色數組)中(它只返回一個布爾值),但我不能說出用戶是什麼角色因爲用戶可能擁有多個角色。

都一樣,我需要知道用戶是否在特定角色。

不反覆的字典,一個For Each,我目前有:

roleList.Select(x => IsInRoles(userInfoObj, new string[] {x.Key}) == true).ToList(); 

注意IsInRoles(params)返回一個布爾值。另外請注意,userInfoObj只是一個在其他地方定義的自定義對象,我實際上無法控制它。

上述語句總是無法過濾IsInRoles返回false的錯誤。我應該改變什麼?

更新:根據評論,我試過簡單的.Where選項並明確聲明...IsInRoles(...) == true。它仍然無法過濾列表。我也明確地檢查過高角色是否包含較低角色(他們沒有)。要明確:

roleList.Where(x => IsInRoles(userInfoObj, new string[] {x.Key}) == true).ToList(); 

roleList.Where(x => IsInRoles(userInfoObj, new string[] {x.Key})).ToList(); 

都同樣會失敗。也就是說,我在字典裏有4個項目,有4個項目出來。測試IsInRoles顯式工作正如我所料,這個函數沒有問題(我們已經使用了它多年)。問題是,whereselect都不會濾除錯誤結果。

人們總是想知道的IsInRoles方法:

public static bool IsInRoles(CurrentUserInfo user, string[] roles, string siteName, bool hasAllRoles) { 
+7

聽起來像你不想使用'選擇'。你想使用['Where'](https://msdn.microsoft.com/en-us/library/bb534803%28v=vs.100%29.aspx)。 –

+3

你的意思是'roleList.Where(r => isInRoles(userInfoObj,r.Key))'? –

+0

。其中(「true statement」)不會過濾掉「false」結果。編輯:堅持下去,我需要檢查角色層次結構,看看更高版本是否包含降低...將更新。 – MetalPhoenix

回答

2

.Select不過濾集合。它返回原始集合的投影 - 可以是新類型,也可以是轉換爲相同類型的新值。 Where用於過濾集合或投影。

但是,你需要捕獲結果Where得到過濾後的值:

var roles = roleList.Where(x => IsInRoles(userInfoObj, new string[] {x.Key})); 

var roles = roleList.Where(x => IsInRoles(userInfoObj, new string[] {x.Key})) 
        .ToList(); 
如果你想滋潤結果列表

您似乎認爲您已經看到它的工作原理,但未將其分配給變量,但Where返回過濾收集的迭代器。如果您不捕獲該返回值,則會丟失。它當然不會就地過濾原始集合。

+0

31eee384對* why爲什麼我的想法有一個很好的評論就是這樣,在看和思考之後,他是對的。無論如何,這必須是一個附加的解決方案:因爲它將進入一個字典(不是列表),它需要以.ToDictionary(x => x.Key,x => x.Value)結尾'謝謝。 – MetalPhoenix

+1

好吧,這是有道理的。 Linq有副作用的另一個原因是一個壞主意。很高興你明白了。 –

1

您可以使用類似:

var roles = roleList.Where(x => IsInRoles(userInfoObj, new string[] {x.Key})) 
        .Select(r => r.Key).ToList(); 

roles與角色的用戶是在一個列表

Select(r => r.Key)只取鑰匙,就是你想知道的角色。

ToList()返回一個過濾結果的列表。

+1

我認爲這裏的關鍵是「ToList()'返回一個結果過濾的列表。」我懷疑提問者在過去已經看到了一些帶有副作用的linq,忽略返回值是有意義的,而'.ToList()'就是強迫評估的地方。 – 31eee384

+0

你擊中了那個位置。最後,我使用一個較輕的版本,只用一個.where然後做.ToDicitonary(x => x.Key,x => x.Value) – MetalPhoenix

0

如果你想只保留該鍵的指定鍵和值,只是簡單地做這

string key = the 'key' role; 
string val = roleList[temp1]; //save the key vand value 
roleList.Clear();    //clear all values 
roleList.Add (key, val);   // add the key and value back 

如果使用選擇(),因爲它是一個功能,您必須將結果賦回到角色列表(但它仍然效率不高)

roleList = roleList.Select(x => IsInRoles(userInfoObj, new string[] {x.Key}) == true).ToList(); 
+0

我不能使用你的建議的前半部分,因爲直到整個字典「迭代」,我不知道要保留哪個鍵和值。用戶可能實際上有5個角色,其中3個屬於特定的角色組,然後我需要從中獲取第一個角色,因爲字典是按照自頂向下的層次結構排序的。另外,.Select需要以.ToDictionary(x => x.Key,x => x.Value)結尾,而不是.ToList() – MetalPhoenix

+0

然後我認爲你應該用'foreach'手動迭代字典,有效比使用「Where」。而對於我的第二個代碼,我錯了,我的道歉。 – DRKblade

相關問題