Reputation: 13491
If I have a dictionary like so,
Dictionary<int, string> roadNames = new Dictionary<int, string>();
roadNames.Add(1, "Rosedale Rd");
roadNames.Add(2, "Transmere Rd");
roadNames.Add(3, "Rosedale Rd");
roadNames.Add(4, "Rosedale Rd");
roadNames.Add(5, "Rosedale Rd");
roadNames.Add(6, "Rosedale Rd");
roadNames.Add(7, "Rosedale Rd");
roadNames.Add(8, "Brown Rd");
roadNames.Add(9, "Harold Rd");
Is there a LINQ solution to remove the duplicates that are NEXT to each other. The result I am after is a list containing this,
Rosedale Rd
Transmere Rd
Rosedale Rd
Brown Rd
Harold Rd
Note that Rosedale Rd is still in the list twice. The idea is to remove duplicates that are next to each other, and in this case we are removing item 4, 5, 6, and 7.
Items 1 is not next to item 3, so it isn't removed.
UPDATE:
Don't worry about Dictionary not being ordered. Solutions for a list that is in order would be fine. I can handle the ordering. i.e.
List<string> roadNames = new List<string>()
{
"Rosedale Rd",
"Transmere Rd",
// etc
};
Upvotes: 4
Views: 2222
Reputation: 117064
Here's a method that uses the standard built-in LINQ operators:
var result =
roadNames
.OrderBy(x => x.Key)
.Select(x => x.Value)
.Aggregate(
new List<string>(),
(xs, x) =>
{
if (xs.LastOrDefault() != x)
{
xs.Add(x);
}
return xs;
});
I've assumed that you want to order by key before selecting the value from the dictionary.
Upvotes: 2
Reputation: 15618
Assuming you're using a sorted dictionary instead (or any other sorted structure), there are two options.
Leverage Reactive Extensions
This is very simple if you leverage Reactive Extensions from Microsoft (which everyone should!):
roadNames.Values // remove if a list instead
.ToObservable()
.DistinctUntilChanged()
.ToList();
You can change that final ToList()
to to ToEnumerable()
instead if you like.
This returns:
Rosedale Rd
Transmere Rd
Rosedale Rd
Brown Rd
Harold Rd
Use an Extension Method
You can use a GroupAdjacent
extension method as such:
roadNames.Values // remove if a list instead
.GroupAdjacent((x,y) => x == y)
.Select(x => x.First());
The extension method:
public static IEnumerable<IEnumerable<T>> GroupAdjacent<T>(
this IEnumerable<T> source, Func<T, T, bool> adjacent)
{
var g = new List<T>();
foreach (var x in source)
{
if (g.Count != 0 && !adjacent(g.Last(), x))
{
yield return g;
g = new List<T>();
}
g.Add(x);
}
yield return g;
}
Upvotes: 2