You can have a boolean as a parameter and select X or Y and Width or Height based on that parameter.  You can declare the method like this:

    private List<Rectangle[]> GroupRectangles(Rectangle[] rectangles, bool horizontally, out int averageGap)

You can use the code from the horizontal method and modify the property calls to use the boolean.  For example, you would replace `rectangle.X` with `horizontally ? rectangle.X : rectangle.Y` and `rectangle.Width` with `horizontally ? rectangle.Width : rectangle.Height`.

It can then be used in your previous methods:

    private List<Rectangle[]> GroupRectanglesHorizontally(Rectangle[] rectangles, out int averageGap)
    {
        return GroupRectangles(rectangles, true, out averageGap);
    }


    private List<Rectangle[]> GroupRectanglesVertically(Rectangle[] rectangles, out int averageGap)
    {
        return GroupRectangles(rectangles, false, out averageGap);
    }

Alternatively, you could have functions as parameters for selecting the properties, like using a lambda expression in `OrderBy()`.