简体   繁体   English

确定给定数字所需的行/列

[英]Determine rows/columns needed given a number

I've got a number of controls (charts in this case) that's determined at runtime.我有许多在运行时确定的控件(在这种情况下是图表)。 I'd like to put these in a grid with the proper number of rows and columns.我想将它们放在一个具有适当行数和列数的网格中。 For example,例如,

  • 4 items = 2 x 2 4 项 = 2 x 2
  • 8 items = 4 x 2 8 件 = 4 x 2
  • 9 items = 3 x 3 9 件 = 3 x 3
  • 20 items = 5 x 4 20 件 = 5 x 4
  • 11 items = 4 x 3 (I don't care about an empty cell) 11 项 = 4 x 3(我不在乎空单元格)

Sorry, I don't really have any code to show my attempts.抱歉,我真的没有任何代码可以显示我的尝试。 I started playing with determining if the square root is an integer, if the number is evenly divisible by 2 etc. and realized I'm not sure how to attack this problem.我开始尝试确定平方根是否为整数,该数字是否可以被 2 整除等,并意识到我不知道如何解决这个问题。 But this is what I'm thinking:但这就是我的想法:

  • If the square root is an integer, use the square root for the number of rows and columns (no problems there)如果平方根是整数,则使用平方根作为行数和列数(没有问题)
  • If not, make sure the number is even (add one if you have to - no problems there)如果不是,请确保数字是偶数(如果必须,请添加一个 - 没有问题)
  • Find the highest two integers that produce the number.找出产生该数字的最大两个整数。 eg If I have 20 controls, the grid should be 5 x 4 and not 10 x 2 (not really sure the best way for this)例如,如果我有 20 个控件,则网格应该是 5 x 4 而不是 10 x 2(不确定最好的方法)

I'd appreciate it if someone could point me in the right direction - or suggest a different algorithm if I'm way off base.如果有人能指出我正确的方向,我将不胜感激 - 或者如果我偏离基地建议不同的算法。

Idea: If square root is not integer, floor it, then divide whole number by this, ceil it.思路:如果平方根不是整数,把它取下,然后除以这个数,取下它。

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

Example: 21 => columns = 4, lines = 6.示例:21 => 列 = 4,行 = 6。

UPDATE: bonus, it also works when sqrt(number) is integer.更新:奖金,它也适用于 sqrt(number) 是整数。 No rounding occurs anywhere, and values are correct.任何地方都没有四舍五入,并且值是正确的。

The "usual" way of handling this problem is by saying that there will always be N columns (less often, always N rows).处理这个问题的“通常”方法是说总是有 N 列(不太经常,总是 N 行)。 The problem then becomes a matter of taking the number of items, dividing by N, and that's the number of rows you have (plus one if there's a remainder).然后问题就变成了取项目数除以 N,这就是您拥有的行数(如果有余数,则加一)。

Changing the size of the grid makes for a confusing user interface.更改网格的大小会导致用户界面混乱。 Users won't understand why the size of the grid keeps changing.用户不会理解为什么网格的大小不断变化。 They won't really wonder about it, but they'll be confused by the seemingly random changes.他们不会真的对此感到怀疑,但他们会被看似随机的变化弄糊涂。

If you still want to do what you're saying, I think you'll need to define your problem a little better.如果你仍然想做你所说的,我认为你需要更好地定义你的问题。 Is there a maximum number of items that can fit on the grid?网格上可以容纳的项目数量是否有上限? Is there a maximum number of columns that you'll allow?是否有允许的最大列数? For example, if you allow 50 items, should they be in 25 rows of 2 items?例如,如果您允许 50 个项目,它们应该在 25 行 2 个项目中吗? 5 rows of 10 items? 5 行 10 个项目? 10 rows of 5 items? 10 行 5 个项目?

At some point you'll have to either scroll horizontally or say, "maximum number of columns is X".在某些时候,您必须水平滚动或说“最大列数为 X”。 And if you're going to impose that maximum number of columns, then you're better off just saying "There will always be X columns."如果您要强加最大数量的列,那么您最好只说“总会有 X 列”。

Unless there's a compelling reason to do the variable-dimension grid that you ask for, you're way better off just fixing the number of columns.除非有令人信服的理由来执行您要求的可变维度网格,否则最好只修复列数。 It makes for trivially simple code rather than some complicated hack, and it presents a much more consistent interface to your users.它使代码变得非常简单,而不是一些复杂的 hack,并且它为您的用户提供了更加一致的界面。

Thank you for this question and answer!感谢您的提问和回答!

Here is the code translated into Javascript:这是翻译成Javascript的代码:

cols = Math.floor( Math.sqrt(totalTiles) );
rows = Math.ceil( totalTiles / cols );

A quick check of @jv42's solution works nicely:快速检查@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);
    }

In WPF the control UniformGrid calculate automatically the rows and columns of grid without determine the rows and columns.在 WPF 中,控件 UniformGrid 自动计算网格的行和列,而无需确定行和列。 for example:例如:

   <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>

Result=> show the images in 3 columns and 3 rows结果=> 以 3 列 3 行显示图像

I had this problem but with some specific requirements;我有这个问题,但有一些特定的要求;

  • The number of columns could never exceed a certain amount列数永远不能超过一定数量
  • If the number of items didn't fit exactly into a certain number of columns I wanted the most amount of widows possible.如果项目数量不完全适合特定数量的列,我想要尽可能多的寡妇。

For example:例如:

1 2 3
4 5 6

1 2 3
4 5

1 2 3 4
5 6 7

I came up with this (PHP) function, I'm sure it can be improved upon though:我想出了这个(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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM