繁体   English   中英

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

[英]Determine rows/columns needed given a number

我有许多在运行时确定的控件(在这种情况下是图表)。 我想将它们放在一个具有适当行数和列数的网格中。 例如,

  • 4 项 = 2 x 2
  • 8 件 = 4 x 2
  • 9 件 = 3 x 3
  • 20 件 = 5 x 4
  • 11 项 = 4 x 3(我不在乎空单元格)

抱歉,我真的没有任何代码可以显示我的尝试。 我开始尝试确定平方根是否为整数,该数字是否可以被 2 整除等,并意识到我不知道如何解决这个问题。 但这就是我的想法:

  • 如果平方根是整数,则使用平方根作为行数和列数(没有问题)
  • 如果不是,请确保数字是偶数(如果必须,请添加一个 - 没有问题)
  • 找出产生该数字的最大两个整数。 例如,如果我有 20 个控件,则网格应该是 5 x 4 而不是 10 x 2(不确定最好的方法)

如果有人能指出我正确的方向,我将不胜感激 - 或者如果我偏离基地建议不同的算法。

思路:如果平方根不是整数,把它取下,然后除以这个数,取下它。

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

示例:21 => 列 = 4,行 = 6。

更新:奖金,它也适用于 sqrt(number) 是整数。 任何地方都没有四舍五入,并且值是正确的。

处理这个问题的“通常”方法是说总是有 N 列(不太经常,总是 N 行)。 然后问题就变成了取项目数除以 N,这就是您拥有的行数(如果有余数,则加一)。

更改网格的大小会导致用户界面混乱。 用户不会理解为什么网格的大小不断变化。 他们不会真的对此感到怀疑,但他们会被看似随机的变化弄糊涂。

如果你仍然想做你所说的,我认为你需要更好地定义你的问题。 网格上可以容纳的项目数量是否有上限? 是否有允许的最大列数? 例如,如果您允许 50 个项目,它们应该在 25 行 2 个项目中吗? 5 行 10 个项目? 10 行 5 个项目?

在某些时候,您必须水平滚动或说“最大列数为 X”。 如果您要强加最大数量的列,那么您最好只说“总会有 X 列”。

除非有令人信服的理由来执行您要求的可变维度网格,否则最好只修复列数。 它使代码变得非常简单,而不是一些复杂的 hack,并且它为您的用户提供了更加一致的界面。

感谢您的提问和回答!

这是翻译成Javascript的代码:

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

快速检查@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);
    }

在 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 行显示图像

我有这个问题,但有一些特定的要求;

  • 列数永远不能超过一定数量
  • 如果项目数量不完全适合特定数量的列,我想要尽可能多的寡妇。

例如:

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

暂无
暂无

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

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