Reputation: 153
I have a list of Privileges. A Privilege class has four properties: Type, AccessType, Value and Action. I want to throw an exception if there are multiple Privileges where the Type, AccessType and Value are the same, BUT the Actions are different.
So for example a list of p1 and p2 would throw an exception:
Privilege p1 = new Privilege{Type = "a", AccessType = "a", Value = "a", Action = "a"};
Privilege p2 = new Privilege{Type = "a", AccessType = "a", Value = "a", Action = "b"};
I would like to use LINQ, but not sure how.
Upvotes: 3
Views: 92
Reputation: 460208
So you want to allow duplicate type+access-type+value but only if the action is also the same?
bool throwException = pList
.GroupBy(x => new { x.Type, x.AccessType, x.Value })
.Any(g => g.Select(p => p.Action).Distinct().Count() > 1);
First i'm building groups of these three properties. Then i check if any of these groups contains multiple actions. Then you can throw the exception.
A small optimization might be(if the duplicate lists are large) if you replace
Distinct().Count() > 1
with
Distinct().Skip(1).Any()
Upvotes: 3
Reputation: 1904
I think the most simple solution here ist using 2 Any()
s.
bool HasDoubleOtherAction = privilegeList.Any(outer => privilegeList
.Any(inner => outer.Type == inner.Type
&& outer.AccessType == inner.AccessType
&& outer.Value == inner.Value
&& outer.Action != inner.Action));
Upvotes: 0
Reputation: 1501926
It sounds like you want to group by Type
, AccessType
and Value
(which you can do with an anonymous type) and then check the actions. Assuming it's okay to have values where the Action
is the same in each case, you could write code like this:
// Normally I'd expect you to have some kind of sequence of privileges rather
// than separate variables.
var privileges = new[] { p1, p2 };
var failures = privileges
// Group the privileges by 3 properties, extracting actions as the values
.GroupBy(p => new { p.Type, p.AccessType, p.Value }, p => p.Action)
// Find any groups which have more than one distinct action
.Where(g => g.Distinct().Skip(1).Any())
.ToList();
if (failures.Count > 0)
{
// There's at least one failure. There may be many. Throw
// whatever exception you want here. This is just an example.
var individualMessages =
failures.Select(g => $"{g.Key}: {string.Join(", ", g.Distinct())}");
throw new Exception(
$"Invalid privilege combinations: {string.Join("; ", individualMessages})");
}
Here's a complete example showing a couple of failures:
using System;
using System.Collections.Generic;
using System.Linq;
class Privilege
{
public string Type { get; }
public string AccessType { get; }
public string Value { get; }
public string Action { get; }
public Privilege(string type, string accessType, string value, string action)
{
Type = type;
AccessType = accessType;
Value = value;
Action = action;
}
}
class Test
{
static void Main()
{
var privileges = new List<Privilege>
{
// Bad: should cause an exception
new Privilege("a", "a", "a", "a"),
new Privilege("a", "a", "a", "b"),
// Another bad one; let's check the
// failure represents both
new Privilege("x", "y", "z", "action1"),
new Privilege("x", "y", "z", "action2"),
// These have one property difference
// in each case
new Privilege("b", "a", "a", "a"),
new Privilege("a", "b", "a", "a"),
new Privilege("a", "a", "b", "a"),
// Duplicate type/access/value, but same action too.
new Privilege("d", "e", "f", "action"),
new Privilege("d", "e", "f", "action")
};
CheckPrivileges(privileges);
}
static void CheckPrivileges(IEnumerable<Privilege> privileges)
{
var failures = privileges
// Group the privileges by 3 properties, extracting actions as the values
.GroupBy(p => new { p.Type, p.AccessType, p.Value }, p => p.Action)
// Find any groups which have more than one distinct action
.Where(g => g.Distinct().Skip(1).Any())
.ToList();
if (failures.Count > 0)
{
// There's at least one failure. There may be many. Throw
// whatever exception you want here. This is just an example.
var individualMessages =
failures.Select(g => $"{g.Key}: {string.Join(", ", g.Distinct())}");
throw new Exception(
$"Invalid privilege combinations: {string.Join("; ", individualMessages)}");
}
}
}
This produces an exception like this (I've added the line breaks):
Unhandled Exception: System.Exception: Invalid privilege combinations:
{ Type = a, AccessType = a, Value = a }: a, b;
{ Type = x, AccessType = y, Value = z }: action1, action2
Upvotes: 3
Reputation: 4598
var duplicates = privilegecollection.GroupBy(x => new {x.Type, x.AccessType, x.Value})
.Where(g => g.Count() > 1)
.Select(g => g.Key);
If duplicates
count is greater than 0 then you can throw exception.
Upvotes: 0