Определите необходимые строки / столбцы с учетом числа - PullRequest
11 голосов
/ 05 ноября 2010

У меня есть несколько элементов управления (в данном случае диаграммы), которые определяются во время выполнения. Я хотел бы поместить их в сетку с правильным количеством строк и столбцов. Например,

  • 4 шт. = 2 х 2
  • 8 предметов = 4 х 2
  • 9 предметов = 3 х 3
  • 20 предметов = 5 х 4
  • 11 предметов = 4 x 3 (мне не важна пустая ячейка)

Извините, у меня нет кода, чтобы показать мои попытки. Я начал играть с определением, является ли квадратный корень целым числом, делится ли число на 2 и т. Д., И понял, что я не уверен, как решить эту проблему. Но вот что я думаю:

  • Если квадратный корень является целым числом, используйте квадратный корень для количества строк и столбцов (проблем нет)
  • Если нет, убедитесь, что номер четный (добавьте его, если нужно - проблем нет)
  • Найдите два старших целых числа, которые дают число. например Если у меня есть 20 элементов управления, сетка должна быть 5 х 4, а не 10 х 2 (не совсем уверен, что для этого лучше)

Буду признателен, если кто-нибудь укажет мне правильное направление или предложит другой алгоритм, если я далеко от базы.

Ответы [ 6 ]

25 голосов
/ 05 ноября 2010

Идея: Если квадратный корень не является целым числом, напишите его, затем разделите на него целое число, а затем - 1001 *

int columns = (int)sqrt(number);
int lines = (int)ceil(number / (float)columns);

Пример: 21 => столбцы = 4, строки = 6.

ОБНОВЛЕНИЕ: бонус, он также работает, когда sqrt (число) является целым числом. Округление нигде не происходит, и значения верны.

3 голосов
/ 05 ноября 2010

Быстрая проверка решения @ jv42 прекрасно работает:

public struct Grid
{
    public int x;
    public int y;

    public Grid(int xx, int yy)
    {
        x = xx;
        y = yy;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Grid g0 = GetGrid(1); Debug.Assert(g0.x == 1 && g0.y == 1);
        Grid g1 = GetGrid(4); Debug.Assert(g1.x == 2 && g1.y == 2);
        Grid g2 = GetGrid(8); Debug.Assert(g2.x == 2 && g2.y == 4);
        Grid g3 = GetGrid(9); Debug.Assert(g3.x == 3 && g3.y == 3);
        Grid g4 = GetGrid(20); Debug.Assert(g4.x == 4 && g4.y == 5);
        Grid g5 = GetGrid(30); Debug.Assert(g5.x == 5 && g5.y == 6);
        Grid g6 = GetGrid(99); Debug.Assert(g6.x == 9 && g6.y == 11);
    }

    public static Grid GetGrid(int n)
    {
        int columns = (int)Math.Sqrt(n);
        int lines   = (int)Math.Ceiling(n / (double)columns);

        return new Grid(columns, lines);
    }
3 голосов
/ 05 ноября 2010

«Обычный» способ решения этой проблемы состоит в том, чтобы сказать, что всегда будет N столбцов (реже всегда N строк). Тогда проблема состоит в том, чтобы взять число элементов, разделив их на N, и это число строк, которые у вас есть (плюс один, если есть остаток).

Изменение размера сетки создает запутанный пользовательский интерфейс. Пользователи не поймут, почему размер сетки постоянно меняется. Они не будут удивляться этому, но будут смущены, казалось бы, случайными изменениями.

Если вы все еще хотите сделать то, что говорите, я думаю, вам нужно определить свою проблему немного лучше. Есть ли максимальное количество предметов, которые можно уместить на сетке? Есть ли максимальное количество столбцов, которые вы позволите? Например, если вы разрешите 50 элементов, должны ли они быть в 25 строках по 2 элемента? 5 рядов по 10 штук? 10 рядов по 5 штук?

В какой-то момент вам придется либо прокрутить горизонтально, либо сказать: «Максимальное количество столбцов - X». И если вы собираетесь навязать это максимальное количество столбцов, то лучше просто сказать: «Всегда будет X столбцов».

Если нет веской причины для создания сетки с переменным измерением, которую вы просите, вам лучше просто зафиксировать количество столбцов. Это делает для тривиально простой код, а не какой-то сложный взлом, и предоставляет гораздо более согласованный интерфейс для ваших пользователей.

1 голос
/ 21 сентября 2016

Спасибо за этот вопрос и ответ!

Вот код, переведенный на Javascript:

cols = Math.floor( Math.sqrt(totalTiles) );
rows = Math.floor(  Math.ceil( totalTiles / cols ) );
0 голосов
/ 16 января 2019

У меня была эта проблема, но с некоторыми особыми требованиями;

  • Количество столбцов никогда не может превышать определенную сумму
  • Если количество элементов не вписывается точно вопределенное количество столбцов, которое я хотел получить как можно больше вдов.

Например:

1 2 3
4 5 6

1 2 3
4 5

1 2 3 4
5 6 7

Я придумал эту (PHP) функцию, я уверен, что она можетбыть улучшено, хотя:

<?php
function optimalColCount ($numItems, $maxCols = 4) {
    $numCols = $numItems;

    if ($numCols > $maxCols and $maxCols === 2) {
        $numCols = 2;
    }
    else if ($numCols > $maxCols) {
        $numCols = sqrt($numItems);

        if (!is_int($numCols) or $numCols > $maxCols) {
            $numCols = -1;

            for ($i = $maxCols; $i > 2; $i--) {
                if ($numItems % $i === 0) {
                    $numCols = $i;

                    break;
                }
            }

            if ($numCols === -1) {
                $rests = [];

                for ($i = $maxCols; $i > 2; $i--) {
                    $rests[$i] = $numItems % $i;
                }

                $numCols = array_search(max($rests), $rests);
            }
        }
    }

    return $numCols;
}
0 голосов
/ 29 июня 2015

В WPF элемент управления UniformGrid вычисляет автоматически строки и столбцы сетки без определения строк и столбцов. например:

   <UniformGrid >
        <Image Source="Images\Aquarium.jpg"  Margin="5"/>
        <Image Source="Images\Ascent.jpg"   Margin="5" />
        <Image Source="Images\Autumn.jpg"  Margin="5"/>
        <Image Source="Images\Crystal.jpg" Margin="5"/>
        <Image Source="Images\DaVinci.jpg"  Margin="5"/>
        <Image Source="Images\Follow.jpg"  Margin="5"/>
        <Image Source="Images\Friend.jpg" Margin="5"/>
        <Image Source="Images\Aquarium.jpg"  Margin="5"/>
    </UniformGrid>

Результат => показать изображения в 3 столбцах и 3 рядах

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...