简体   繁体   中英

Filter Dictionary<string, string> using LINQ select

I have a Dictionary<string, string> called roleList . In this case, roleList lists the role and the role right above that role in hierarchy - I need to preserve both key and value for the item matching the 'key' role and can discard the rest.

I also have access to a function previously written which will let me know if the user is in a specific role (or array of roles) (it returns only a boolean) but I can't tell what role is a user in because the user might hold several roles.

All the same, I need to know if the user is in a specific role.

Without iterating the dictionary with a For Each , I currently have:

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

Note that IsInRoles(params) returns a boolean. Also note that userInfoObj is just a custom object that is defined elsewhere and I really don't have control over it.

The above statement always fails to filter out the ones where IsInRoles returns false. What ought I change?

Update: per comments, I have tried the plain .Where option and explicitly stating ...IsInRoles(...) == true . It still fails to filter the list. I have also explicitly checked to see if higher roles include lower roles (they do not). To be explicit:

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

and

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

both fail equally. That is to say that I have 4 items in the dictionary going in and 4 coming out. Testing IsInRoles explicitly works as I would expect, there is no problem with that function (we've been using it for years). The problem is that neither where nor select filter out the false results.

People keep wanting to know the IsInRoles method:

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

.Select does not filter a collection. It returns a projection of the original collection - either a new type or a transformation to a new value of the same type. Where is used to filter a collection or projection.

However, you need to capture the result of Where to get the filtered values:

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

or

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

if you want to hydrate the results to a list.

You seem to think that you have seen it work without assigning it to a variable, but Where returns an iterator that filters the collection. If you do not capture that return value then it gets lost. It certainly does not filter the original collection in-place.

You can use something like:

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

roles is a list with the roles a user is in.

The Select(r => r.Key) take only the keys, that is, the roles you want to know.

The ToList() returns a list with the result filtered.

If you want to preserve only the specified key and value of that key, just simply do this

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

If you use Select (), since it is a function, you have to assign the result back to roleList (but still it isn't efficient)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM