score:1

Just an another idea of a clustering with using `GroupBy` with a custom comparer

``````var numbers = new float[]
{
3.4f, 5.0f, 6.1f, 144.0f, 144.14f, 145.0f,
147.0f, 273.77f, 275.19f, 279.0f, 399.4f, 399.91f, 401.45f,
49, 50, 51,
533.26f, 537.0f, 538.9f
};

foreach (var group in numbers.GroupBy(i => i, new ClosenessComparer(4f)))
Console.WriteLine(string.Join(", ", group));
``````

And the custom `ClosenessComparer`:

``````public class ClosenessComparer : IEqualityComparer<float>
{

public ClosenessComparer(float delta)
{
this.delta = delta;
}

public bool Equals(float x, float y)
{
return Math.Abs((x + y)/ 2f - y) < delta;
}

public int GetHashCode(float obj)
{
return 0;
}
}
``````

And the output:

``````1: 3,4 5 6,1
2: 144 144,14 145 147
3: 273,77 275,19 279
4: 399,4 399,91 401,45
6: 49 50 51
5: 533,26 537 538,9
``````

score:1

Here's a method that groups elements if they're within a certain delta (4 by default) of the previous value:

``````IEnumerable<IEnumerable<double>> GetClusters(IEnumerable<double> data,
double delta = 4.0)
{
var cluster = new List<double>();
foreach (var item in data.OrderBy(x=>x))
{
if (cluster.Count > 0 && item > cluster[cluster.Count - 1] + delta)
{
yield return cluster;
cluster = new List<double>();
}
You can get tweak the algorithm by changing what you use for `cluster[cluster.Count - 1] + delta`. For example, you might use
• `cluster + delta` - delta from first element in the cluster
• `cluster.Average() + delta` - delta from the mean of the cluster so far
• `cluster[cluster.Count / 2] + delta` - delta from the median of the cluster so far