【问题标题】:Fastest way to generate a color that is not in an array of colors生成不在颜色数组中的颜色的最快方法
【发布时间】:2012-01-12 09:46:33
【问题描述】:

我想知道解决这个问题的最佳方法是什么......

我有一组用户定义的颜色,它们作为 rgb 值被推入堆栈。我想为每个用户定义的颜色找到第二种颜色。这些第二种颜色在用户定义的数组中必须是完全唯一的,但可以是完全随机的,不需要与任何用户颜色有任何视觉关系。

生成随机 rgb 值并针对堆栈进行测试会很快,因为随机数不太可能在第一次尝试时找到相同的颜色。或者只是从 255,254,253 开始并从每个值中减去 1,然后针对堆栈进行测试会更好,也不太可能并且操作更少。还是有其他想法?

【问题讨论】:

  • 所有原始颜色接近 (255,255,255) 的可能性有多大?如果是,那么随机选择似乎是更好的选择。
  • 你在接下来的 5 分钟内实现的那个,除非它证明太慢:) 我会选择随机数,因为那样它实际上可能有点有趣, 不管是什么。对于较小的初始数组,没有必要切换到地图和/或使用更复杂的树/算法。
  • 另外,堆栈似乎不是这个任务的最佳数据结构......
  • 使用随机数。没有理由不这样做。
  • @OliCharlesworth 我将把它添加到“没有区别的浪费周期桶”;-)

标签: javascript arrays performance optimization


【解决方案1】:

下面是一些代码:

var colors = [];

function getRandUniqColor()
{
    var r = getRGBString(),
        g = getRGBString(),
        b = getRGBString(),
        rgb = r + g + b;

    if ( colors.indexOf(rgb) == -1 )
    {
        colors.push(rgb);
        return {
            r: r,
            g: g,
            b: b
        }
    }
    else
    {
        return getRandUniqColor()
    }
}

function getRGBString()
{
    var num = Math.floor( Math.random() * 255 ).toString();
    while (num.length < 3)
    {
        num = '0' + num;
    }
    return num;
}

只需调用getRandUniqColor(),您将获得一个包含 RGB 值的对象字面量。

注意:如果涉及很多颜色,则不应使用递归函数。

...这是小提琴:http://jsfiddle.net/wV6Mw/

【讨论】:

  • 是的,我相信这将是我最有效的方式(考虑到我正在尝试做的事情,其中​​大部分我都没有讨论过)。我喜欢你在数字前加 0 的方式,我还没有看到这种方式。
  • @andbeyond - 哦,我多么希望我能在 JavaScript 中做 str_pad($num, 3, "0", STR_PAD_LEFT)!附带说明:不要忘记为 IE 填充 indexOf
  • 不应该 OP 生成与现有颜色有一定距离的新颜色(因此它们明显不同),而不仅仅是一点点不同?
  • 我也可以使用 toString 将所有值(用户定义和计算机定义)转换为十六进制值并进行比较,以在整个应用程序中保持标准。
  • @jfriend00 - OP clearly doesn't care 关于这个...
【解决方案2】:

我建议生成随机 RGB 值(组合三个随机数),然后创建一个函数来测量生成的随机颜色与数据结构中的随机颜色之间的色差。如果您生成的颜色与您已有的颜色太接近,请生成一个新颜色。您将必须决定您希望随机颜色与您已有的颜色有多“不同”,但 R、G 和 B 中只有几个点的差异不会有明显的不同,因此您应该寻找一些最小值至少在一个通道中分离。

搜索“计算 rgb 色差”为您提供了一堆关于如何计算两个颜色值之间有意义的差异的参考资料。来自该搜索的这个link 有一个特定的方程式,这里有一个关于颜色差异的previous question on SO

如果您只想要不同的颜色而不需要/想要真正随机的颜色,您也可以从已有的颜色中生成互补色。

您可以以数据形式或十六进制字符串形式生成这样的随机颜色:

// generate r,g,b data structure like {r: 255, g: 30, b: 09}
function generateRandomColorData() {
    function randomColorVal() {
        return(Math.floor(Math.random() * 256));
    }
    return {r:randomColorVal(), g: randomeColorVal(), b: randomColorVal()};
}

// generate hex string color value like FF4409
function generateRandomColorHex() {
    function randomColorVal() {
        var val = Math.floor(Math.random() * 256).toString(16);
        if (val.length < 2) {
            val = "0" + val;
        }
        return(val);
    }
    return(randomColorVal() + randomColorVal() + randomColorVal());
}

【讨论】:

  • 重申一下,生成的颜色不需要与任何用户颜色有任何视觉关系,它可以只偏离一个值,我会很高兴,用户永远不会看到这些颜色。
  • @andbeyond 那么为什么不将数字作为 9 个字符串存储在一个数组中,然后只检查数组中随机生成的字符串呢?
  • @JosephSilber:在我的脑海中,这听起来可能是迄今为止最好的想法。因为这意味着我只需要生成一个介于 1 和 255255255 之间的随机数。
  • @andbeyond - 错误。你不能通过在这些值之间生成一个随机数来做到这一点,因为你可能会得到像184736256 这样的东西,它超出了范围。您仍然需要在 0-255 范围内生成三个单独的数字,但是您可以将它们连接起来(用 0 填充它们之后),并轻松检查它们是否在您的数组中。
  • @JosephSilber:是的,很明显,每当我不经意间想到我就错了!谢谢,虽然我仍然相信这更容易。
【解决方案3】:

正如其他人所说,最简单的方法可能是创建随机颜色并检查冲突。

如果您要大量填充颜色空间(用户选择数百万种颜色),那么另一种方法是创建一个 256^3 位的颜色立方体,并让“1”代表使用的颜色。然后你可以从位置 0 开始,使用第一个“0”作为生成的颜色,下一个“0”作为第二个,依此类推。数据结构将超过 2 MB 的内存。

但随机可能是要走的路。

【讨论】:

    猜你喜欢
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    相关资源
    最近更新 更多