Reputation: 49
Have a list with deviceIds and corresponding actions to be taken on device.
var results= new List<Result>
{
new Result{ DeviceId= 1, ActionType = 1 },
new Result{ DeviceId= 1, ActionType = 2 },
new Result{ DeviceId= 1, ActionType = 3 },
new Result{ DeviceId= 2, ActionType = 1 },
new Result{ DeviceId= 3, ActionType = 1 },
new Result{ DeviceId= 4, ActionType = 1 },
new Result{ DeviceId= 5, ActionType = 1 },
new Result{ DeviceId= 6, ActionType = 1 },
new Result{ DeviceId= 6, ActionType = 2 },
};
How do I filter deviceIds unique in the list(no DeviceId 1), and assign it back to var "results"
results = List<Result>
{
new Result{ DeviceId= 2, ActionType = 1 },
new Result{ DeviceId= 3, ActionType = 1 },
new Result{ DeviceId= 4, ActionType = 1 },
new Result{ DeviceId= 5, ActionType = 1 },
};
Have tried using groupby and couldn't move forward
results = from result in results
group result by result.DeviceId
into groupedResultsByDevice
where groupedResultsByDevice.Count() == 1
select ????
Upvotes: 0
Views: 119
Reputation: 4778
Check this out
public static void Main()
{
var results = new List<Result>
{
new Result {DeviceId = 1, ActionType = 1},
new Result {DeviceId = 1, ActionType = 2},
new Result {DeviceId = 1, ActionType = 3},
new Result {DeviceId = 2, ActionType = 1},
new Result {DeviceId = 3, ActionType = 1},
new Result {DeviceId = 4, ActionType = 1},
new Result {DeviceId = 5, ActionType = 1},
new Result {DeviceId = 6, ActionType = 1},
new Result {DeviceId = 6, ActionType = 2},
};
List<Result> result = results
.GroupBy(x => x.DeviceId)
.Where(x => x.Count() == 1)
.SelectMany(x => x)
.Distinct()
.ToList();
result.ForEach(Console.WriteLine);
Console.ReadLine();
}
public sealed class Result : IEqualityComparer<Result>
{
public int DeviceId { get; set; }
public int ActionType { get; set; }
public bool Equals(Result x, Result y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
if (x.GetType() != y.GetType()) return false;
return x.DeviceId == y.DeviceId && x.ActionType == y.ActionType;
}
public int GetHashCode(Result obj)
{
unchecked
{
return (obj.DeviceId*397) ^ obj.ActionType;
}
}
public override string ToString()
{
return string.Format("DeviceId: {0}, ActionType: {1}", DeviceId, ActionType);
}
}
Result output:
DeviceId: 2, ActionType: 1
DeviceId: 3, ActionType: 1
DeviceId: 4, ActionType: 1
DeviceId: 5, ActionType: 1
Upvotes: 0
Reputation: 16878
Besides answer with query syntax, in method syntax LINQ query it will be:
results = results.GroupBy(r => r.DeviceId)
.Where(g => g.Key != 1 && g.Count() == 1)
.Select(g => g.First())
.ToList();
Upvotes: 1
Reputation: 125630
results = from r in results
group r by r.DeviceId into g
where g.Count() == 1
select g.First()
You can make it a little bit more efficient replacing g.Count()
with !g.Skip(1).Any()
:
results = from r in results
group r by r.DeviceId into g
where !g.Skip(1).Any()
select g.First()
It will return false
as soon as second element is found, instead of counting all items in the group.
Upvotes: 1
Reputation: 40200
After grouping you can select the first (and only element of the group):
results = from result in results
group result by result.DeviceId
into groupedResultsByDevice
where groupedResultsByDevice.Count() == 1
select groupedResultsByDevice.First(); // <---
Upvotes: 1