1

Let's say I have a collection of elements which have a float property.

I was grouping by it but I found I was getting undesired groupings.

For example (with a double to take profit of Random's NextDouble()):

void Main()
{
    var examples = new List<Example>();
    var rnd = new Random();
    for (int i = 0; i < 100; i++)
    {
        var newPosition = rnd.NextDouble();
        examples.Add(new Example { Position = newPosition });
    }
    
    examples.GroupBy(x => x.Position).Dump();
}

class Example
{
    public double Position { get; set; }
}

This would lead into something like this:

Grouping 0,00075609376689237252

Grouping 0,0010980092925475954

Grouping 0,0020200186418462629

Grouping 0,0062832017458431429

...

Question is (worthy or not): how could I group them by allowing to have a "boundary" like... +- 0.05?

Community
  • 1
  • 1
Gonzo345
  • 1,133
  • 3
  • 20
  • 42
  • 3
    Round your double to the desired approximation in the groupby ? lik ehttps://dotnetfiddle.net/5s9jkR – xdtTransform May 13 '19 at 09:14
  • Is rounding a good enought solution or you need the +- 0.05? in this case we will need a predefine set of 10 value with a step of 0.01 so we can understand how you group them together? – xdtTransform May 13 '19 at 09:20
  • @xdtTransform Thanks for the tip! Rounding seems good enough since it does the job and yes, I guess the first group (0.00~0.05) would do the 10 set group. – Gonzo345 May 13 '19 at 09:23
  • The other way is possible With a group of value for each value. In my exemple range the result will look like https://i.stack.imgur.com/VlGtI.png – xdtTransform May 13 '19 at 09:34

1 Answers1

3

The boundary of +-0.05 is a bit unclear:

For a set like : { 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1 }
Each value is 0.01 for the next but but all are in the [+-0.05] range from 0.05.
But 0.01 and 0.06 are too far from each other.

But rounding to the 2nd decimal could be enought.

examples.GroupBy(x => Math.Round( x.Position,2))

As bleep-bloop commented:

if you want to group by sets of 0,05 you could do x => Math.Round(x.Position / 0.05)

MCVE:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public void Main()
    {
        var examples = new List<Example>();
        var rnd = new Random();
        for (int i = 0; i < 100; i++)
        {
            var newPosition = rnd.NextDouble();
            examples.Add(new Example { Position = newPosition });
        }

        examples.GroupBy(x => Math.Round( x.Position,2)).Dump();


        examples.GroupBy(x => x => Math.Round(x.Position / 0.05)).Dump();
    }

    public class Example
    {
        public double Position { get; set; }
    }
}

Live exemple : https://dotnetfiddle.net/LDNBgu

xdtTransform
  • 1,986
  • 14
  • 34
  • To add to that if you would want to group by sets of `0,05` you could do `x => Math.Round(x.Position / 0.05)`. Added to that it's also a bit more readable. – NotFound May 13 '19 at 09:36
  • @Bleep-Bloop: Yes, add to that that what you suggest actually groups with a whole number as a key, and the OP could then cast to int to avoid comparing floats. – Laurent LA RIZZA May 13 '19 at 09:41
  • @LaurentLARIZZA I don't think rounding the floats for a `GroupBy` could end up with inequality from the `Math.Round` method, while casting could overflow (although not for this particular situation). – NotFound May 13 '19 at 09:48
  • @bleep, Added in the answer with an attribution link to your profil. You can edit anything related to that part if you want. – xdtTransform May 13 '19 at 09:58