using System;
using System.Globalization;
using System.Linq;
using System.Collections.Generic;
public class Test
{
public static void Main()
{
var words = new List<string>{"golf", "hip", "hop", "hotel", "grass", "world", "wee"};
IEnumerable<string> lastWordOfConsecutiveFirstCharGroups = words
.GroupAdjacent(str => str[0])
.Select(g => g.Last());
Console.WriteLine(string.Join(",",lastWordOfConsecutiveFirstCharGroups.ToArray()));
words=new List<string>{"apples", "armies", "black", "beer", "bastion", "cat", "cart", "able", "art", "bark"};
lastWordOfConsecutiveFirstCharGroups = words
.GroupAdjacent(str => str[0])
.Select(g => g.Last());
Console.WriteLine(string.Join(",",lastWordOfConsecutiveFirstCharGroups.ToArray()));
}
}
public static class Extensions
{
public static IEnumerable<IGrouping<TKey, TSource>> GroupAdjacent<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector)
{
TKey last = default(TKey);
bool haveLast = false;
List<TSource> list = new List<TSource>();
foreach (TSource s in source)
{
TKey k = keySelector(s);
if (haveLast)
{
if (!k.Equals(last))
{
yield return new GroupOfAdjacent<TSource, TKey>(list, last);
list = new List<TSource>();
list.Add(s);
last = k;
}
else
{
list.Add(s);
last = k;
}
}
else
{
list.Add(s);
last = k;
haveLast = true;
}
}
if (haveLast)
yield return new GroupOfAdjacent<TSource, TKey>(list, last);
}
public class GroupOfAdjacent<TSource, TKey> : IEnumerable<TSource>, IGrouping<TKey, TSource>
{
public TKey Key { get; set; }
private List<TSource> GroupList { get; set; }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return ((System.Collections.Generic.IEnumerable<TSource>)this).GetEnumerator();
}
System.Collections.Generic.IEnumerator<TSource> System.Collections.Generic.IEnumerable<TSource>.GetEnumerator()
{
foreach (var s in GroupList)
yield return s;
}
public GroupOfAdjacent(List<TSource> source, TKey key)
{
GroupList = source;
Key = key;
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uR2xvYmFsaXphdGlvbjsKdXNpbmcgU3lzdGVtLkxpbnE7CnVzaW5nIFN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljOwoKcHVibGljIGNsYXNzIFRlc3QKewoJcHVibGljIHN0YXRpYyB2b2lkIE1haW4oKQoJewoJCXZhciB3b3JkcyA9IG5ldyBMaXN0PHN0cmluZz57ImdvbGYiLCAiaGlwIiwgImhvcCIsICJob3RlbCIsICJncmFzcyIsICJ3b3JsZCIsICJ3ZWUifTsKCSAgICBJRW51bWVyYWJsZTxzdHJpbmc+IGxhc3RXb3JkT2ZDb25zZWN1dGl2ZUZpcnN0Q2hhckdyb3VwcyA9IHdvcmRzCgkgICAgICAgIC5Hcm91cEFkamFjZW50KHN0ciA9PiBzdHJbMF0pCgkgICAgICAgIC5TZWxlY3QoZyA9PiBnLkxhc3QoKSk7CgkgICAgQ29uc29sZS5Xcml0ZUxpbmUoc3RyaW5nLkpvaW4oIiwiLGxhc3RXb3JkT2ZDb25zZWN1dGl2ZUZpcnN0Q2hhckdyb3Vwcy5Ub0FycmF5KCkpKTsKCQoJICAgIHdvcmRzPW5ldyBMaXN0PHN0cmluZz57ImFwcGxlcyIsICJhcm1pZXMiLCAiYmxhY2siLCAiYmVlciIsICJiYXN0aW9uIiwgImNhdCIsICJjYXJ0IiwgImFibGUiLCAiYXJ0IiwgImJhcmsifTsKCSAgICBsYXN0V29yZE9mQ29uc2VjdXRpdmVGaXJzdENoYXJHcm91cHMgPSB3b3JkcwoJICAgICAgIC5Hcm91cEFkamFjZW50KHN0ciA9PiBzdHJbMF0pCgkgICAgICAgLlNlbGVjdChnID0+IGcuTGFzdCgpKTsKCSAgICBDb25zb2xlLldyaXRlTGluZShzdHJpbmcuSm9pbigiLCIsbGFzdFdvcmRPZkNvbnNlY3V0aXZlRmlyc3RDaGFyR3JvdXBzLlRvQXJyYXkoKSkpOwoJfQp9CgpwdWJsaWMgc3RhdGljIGNsYXNzIEV4dGVuc2lvbnMKewogICAgcHVibGljIHN0YXRpYyBJRW51bWVyYWJsZTxJR3JvdXBpbmc8VEtleSwgVFNvdXJjZT4+IEdyb3VwQWRqYWNlbnQ8VFNvdXJjZSwgVEtleT4oCiAgICAgICAgdGhpcyBJRW51bWVyYWJsZTxUU291cmNlPiBzb3VyY2UsCiAgICAgICAgRnVuYzxUU291cmNlLCBUS2V5PiBrZXlTZWxlY3RvcikKICAgIHsKICAgICAgICBUS2V5IGxhc3QgPSBkZWZhdWx0KFRLZXkpOwogICAgICAgIGJvb2wgaGF2ZUxhc3QgPSBmYWxzZTsKICAgICAgICBMaXN0PFRTb3VyY2U+IGxpc3QgPSBuZXcgTGlzdDxUU291cmNlPigpOwogICAgICAgIGZvcmVhY2ggKFRTb3VyY2UgcyBpbiBzb3VyY2UpCiAgICAgICAgewogICAgICAgICAgICBUS2V5IGsgPSBrZXlTZWxlY3RvcihzKTsKICAgICAgICAgICAgaWYgKGhhdmVMYXN0KQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiAoIWsuRXF1YWxzKGxhc3QpKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHlpZWxkIHJldHVybiBuZXcgR3JvdXBPZkFkamFjZW50PFRTb3VyY2UsIFRLZXk+KGxpc3QsIGxhc3QpOwogICAgICAgICAgICAgICAgICAgIGxpc3QgPSBuZXcgTGlzdDxUU291cmNlPigpOwogICAgICAgICAgICAgICAgICAgIGxpc3QuQWRkKHMpOwogICAgICAgICAgICAgICAgICAgIGxhc3QgPSBrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGxpc3QuQWRkKHMpOwogICAgICAgICAgICAgICAgICAgIGxhc3QgPSBrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgbGlzdC5BZGQocyk7CiAgICAgICAgICAgICAgICBsYXN0ID0gazsKICAgICAgICAgICAgICAgIGhhdmVMYXN0ID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoaGF2ZUxhc3QpCiAgICAgICAgICAgIHlpZWxkIHJldHVybiBuZXcgR3JvdXBPZkFkamFjZW50PFRTb3VyY2UsIFRLZXk+KGxpc3QsIGxhc3QpOwogICAgfQoKICAgIHB1YmxpYyBjbGFzcyBHcm91cE9mQWRqYWNlbnQ8VFNvdXJjZSwgVEtleT4gOiBJRW51bWVyYWJsZTxUU291cmNlPiwgSUdyb3VwaW5nPFRLZXksIFRTb3VyY2U+CiAgICB7CiAgICAgICAgcHVibGljIFRLZXkgS2V5IHsgZ2V0OyBzZXQ7IH0KICAgICAgICBwcml2YXRlIExpc3Q8VFNvdXJjZT4gR3JvdXBMaXN0IHsgZ2V0OyBzZXQ7IH0KICAgICAgICBTeXN0ZW0uQ29sbGVjdGlvbnMuSUVudW1lcmF0b3IgU3lzdGVtLkNvbGxlY3Rpb25zLklFbnVtZXJhYmxlLkdldEVudW1lcmF0b3IoKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuICgoU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuSUVudW1lcmFibGU8VFNvdXJjZT4pdGhpcykuR2V0RW51bWVyYXRvcigpOwogICAgICAgIH0KICAgICAgICBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5JRW51bWVyYXRvcjxUU291cmNlPiBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5JRW51bWVyYWJsZTxUU291cmNlPi5HZXRFbnVtZXJhdG9yKCkKICAgICAgICB7CiAgICAgICAgICAgIGZvcmVhY2ggKHZhciBzIGluIEdyb3VwTGlzdCkKICAgICAgICAgICAgICAgIHlpZWxkIHJldHVybiBzOwogICAgICAgIH0KICAgICAgICBwdWJsaWMgR3JvdXBPZkFkamFjZW50KExpc3Q8VFNvdXJjZT4gc291cmNlLCBUS2V5IGtleSkKICAgICAgICB7CiAgICAgICAgICAgIEdyb3VwTGlzdCA9IHNvdXJjZTsKICAgICAgICAgICAgS2V5ID0ga2V5OwogICAgICAgIH0KICAgIH0KfQ==