using System;
using System.Collections ;
using System.Collections .Generic ;
using System.Linq ;
using System.Text ;
namespace GroupByCluster
{
public static class EnumerableExtensions
{
class ClusterGrouping< T> : IGrouping< T, T>
{
public T Key { get; private set; }
public IEnumerator< T> GetEnumerator( )
{
return items.GetEnumerator ( ) ;
}
IEnumerator IEnumerable.GetEnumerator ( )
{
return GetEnumerator( ) ;
}
internal readonly List< T> items = new List< T> ( ) ;
internal ClusterGrouping( T t)
{
Key = t;
items.Add ( t) ;
}
internal ClusterGrouping( IEnumerable< ClusterGrouping< T>> containingGroups)
{
Key = containingGroups.First ( ) .Key ;
items.AddRange ( containingGroups.SelectMany ( g => g) ) ;
}
internal void Include( T t)
{
items.Add ( t) ;
}
}
public static IEnumerable< IGrouping< T, T>> GroupByCluster< T> ( this IEnumerable< T> source, Func< T, T, double> distance, double eps)
{
var result = new HashSet< ClusterGrouping< T>> ( ) ;
foreach ( T t in source)
{
// need to materialize, as we are changing the result
var containingGroups = result.Where ( g => g.Any ( gt => distance( t, gt) < eps) ) .ToList ( ) ;
switch ( containingGroups.Count )
{
case 0 :
result.Add ( new ClusterGrouping< T> ( t) ) ;
break ;
case 1 :
containingGroups[ 0 ] .Include ( t) ;
break ;
default :
result.Add ( new ClusterGrouping< T> ( containingGroups) ) ;
foreach ( var g in containingGroups)
result.Remove ( g) ;
break ;
}
}
return result;
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uQ29sbGVjdGlvbnM7CnVzaW5nIFN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljOwp1c2luZyBTeXN0ZW0uTGlucTsKdXNpbmcgU3lzdGVtLlRleHQ7CgpuYW1lc3BhY2UgR3JvdXBCeUNsdXN0ZXIKewogICAgcHVibGljIHN0YXRpYyBjbGFzcyBFbnVtZXJhYmxlRXh0ZW5zaW9ucwogICAgewogICAgICAgIGNsYXNzIENsdXN0ZXJHcm91cGluZzxUPiA6IElHcm91cGluZzxULCBUPgogICAgICAgIHsKICAgICAgICAgICAgcHVibGljIFQgS2V5IHsgZ2V0OyBwcml2YXRlIHNldDsgfQoKICAgICAgICAgICAgcHVibGljIElFbnVtZXJhdG9yPFQ+IEdldEVudW1lcmF0b3IoKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXR1cm4gaXRlbXMuR2V0RW51bWVyYXRvcigpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBJRW51bWVyYXRvciBJRW51bWVyYWJsZS5HZXRFbnVtZXJhdG9yKCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmV0dXJuIEdldEVudW1lcmF0b3IoKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaW50ZXJuYWwgcmVhZG9ubHkgTGlzdDxUPiBpdGVtcyA9IG5ldyBMaXN0PFQ+KCk7CgogICAgICAgICAgICBpbnRlcm5hbCBDbHVzdGVyR3JvdXBpbmcoVCB0KQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBLZXkgPSB0OwogICAgICAgICAgICAgICAgaXRlbXMuQWRkKHQpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpbnRlcm5hbCBDbHVzdGVyR3JvdXBpbmcoSUVudW1lcmFibGU8Q2x1c3Rlckdyb3VwaW5nPFQ+PiBjb250YWluaW5nR3JvdXBzKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBLZXkgPSBjb250YWluaW5nR3JvdXBzLkZpcnN0KCkuS2V5OwogICAgICAgICAgICAgICAgaXRlbXMuQWRkUmFuZ2UoY29udGFpbmluZ0dyb3Vwcy5TZWxlY3RNYW55KGcgPT4gZykpOwogICAgICAgICAgICB9CiAgICAgICAgCiAgICAgICAgICAgIGludGVybmFsIHZvaWQgSW5jbHVkZShUIHQpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGl0ZW1zLkFkZCh0KTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIHN0YXRpYyBJRW51bWVyYWJsZTxJR3JvdXBpbmc8VCwgVD4+IEdyb3VwQnlDbHVzdGVyPFQ+KHRoaXMgSUVudW1lcmFibGU8VD4gc291cmNlLCBGdW5jPFQsIFQsIGRvdWJsZT4gZGlzdGFuY2UsIGRvdWJsZSBlcHMpCiAgICAgICAgewogICAgICAgICAgICB2YXIgcmVzdWx0ID0gbmV3IEhhc2hTZXQ8Q2x1c3Rlckdyb3VwaW5nPFQ+PigpOwogICAgICAgICAgICBmb3JlYWNoIChUIHQgaW4gc291cmNlKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLyBuZWVkIHRvIG1hdGVyaWFsaXplLCBhcyB3ZSBhcmUgY2hhbmdpbmcgdGhlIHJlc3VsdAogICAgICAgICAgICAgICAgdmFyIGNvbnRhaW5pbmdHcm91cHMgPSByZXN1bHQuV2hlcmUoZyA9PiBnLkFueShndCA9PiBkaXN0YW5jZSh0LCBndCkgPCBlcHMpKS5Ub0xpc3QoKTsKICAgICAgICAgICAgICAgIHN3aXRjaCAoY29udGFpbmluZ0dyb3Vwcy5Db3VudCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgICByZXN1bHQuQWRkKG5ldyBDbHVzdGVyR3JvdXBpbmc8VD4odCkpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICAgIGNvbnRhaW5pbmdHcm91cHNbMF0uSW5jbHVkZSh0KTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LkFkZChuZXcgQ2x1c3Rlckdyb3VwaW5nPFQ+KGNvbnRhaW5pbmdHcm91cHMpKTsKICAgICAgICAgICAgICAgICAgICBmb3JlYWNoICh2YXIgZyBpbiBjb250YWluaW5nR3JvdXBzKQogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuUmVtb3ZlKGcpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgfQp9
compilation info
prog.cs(67,13): error CS0266: Cannot implicitly convert type `System.Collections.Generic.HashSet<GroupByCluster.EnumerableExtensions.ClusterGrouping<T>>' to `System.Collections.Generic.IEnumerable<System.Linq.IGrouping<T,T>>'. An explicit conversion exists (are you missing a cast?)
Compilation failed: 1 error(s), 0 warnings
stdout