在 Ruby 中将一个大散列划分为 N 个较小散列的最有效方法是什么?

2024-02-28

问题


我正在研究一个涉及分片的问题。作为问题的一部分,我需要找到最快的方法将大型 Rub​​y 散列(> 200,0000 个条目)划分为两个或更多部分。

  • 有没有非 O(n) 的方法?

  • 是否有非 Ruby 即 C/C++ 实现?

请不要使用将哈希转换为数组并重建 N 个不同哈希的简单方法来回复示例。

我担心的是 Ruby 做这种工作太慢了。

最初的方法


这是我尝试的第一个解决方案。它的吸引力在于:

  • 它不需要盲目地循环遍历哈希
  • 它不需要管理计数器来在分片之间均匀分配成员。
  • 它看起来又短又整洁

好吧,它不是 O(n),但它依赖于标准库中的方法,我认为这比编写我自己的 Ruby 代码更快。

pivot = s.size / 2

slices = s.each_slice(pivot)

s1 = Hash[*slices.entries[0].flatten]

s2 = Hash[*slices.entries[1].flatten]

更好的解决方案

马克和迈克很友善地提出了一些方法。我不得不承认马克的方法感觉是错误的 - 它确实做了我不想要的事情 - 它循环了所有的成员并评估了一个条件 - 但因为他花时间做了评估,我认为我应该尝试类似的方法并对其进行基准测试。这是我对其方法的改编版本(我的密钥不是数字,所以我不能逐字接受他的方法)

def split_shard(s)
    shard1 = {}
    shard2 = {}


    t = Benchmark.measure do
        n = 0

        pivot = s.size / 2

        s.each_pair do |k,v|
            if n < pivot
                shard1[k] = v
            else
                shard2[k] = v
            end

            n += 1
        end
    end

    $b += t.real
    $e += s.size
    return shard1, shard2
end

结果


在这两种情况下,大量的哈希值都会被分割成碎片。测试数据集中所有散列的元素总数为 1,680,324。

我最初的解决方案 - 它必须更快,因为它使用标准库中的方法并最大限度地减少 Ruby 代码量(无循环,无条件) - 运行时间刚好超过9s

马克的方法刚刚结束5s

这是一场重大胜利

带走


不要被“直觉”愚弄 - 衡量竞争算法的性能

不要担心 Ruby 作为一种语言的性能 - 我最初担心的是,如果我要执行一千万次这样的操作,那么在 Ruby 中可能会花费大量时间,但事实并非如此。

感谢马克和迈克,他们的帮助都从我这里得到了积分。

Thanks!


我不知道如何使用未经修改的“普通”哈希来实现这一点 - 我希望您需要进入内部才能将分区划分为某种批量内存复制操作。你的C有多好?

我更倾向于研究分区instead首先创建哈希,特别是如果 200K 项哈希存在的唯一原因是要细分的话。

编辑:在健身房思考之后......

寻找现有解决方案的问题在于,其他人需要(a)经历过痛苦,(b)拥有解决该问题的技术能力,以及(c)感到社区足够友好以将其释放到野外。哦,还有你的操作系统平台。

使用 B 树而不是哈希怎么样?保存按键排序的数据,可以通过 memcpy() 遍历它。 B-Tree 检索的时间复杂度为 O(log N),大多数时候这对 Hash 来说影响不大。

我发现了一些东西here http://scripts.top4download.com/generic-data-structures-library/cmlvl.html这可能会有所帮助,而且我希望只需要一个小鸭子打字包装器就可以使它像哈希一样嘎嘎作响。

不过,仍然需要那些 C/C++ 技能。 (我的已经生锈得无可救药了)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Ruby 中将一个大散列划分为 N 个较小散列的最有效方法是什么? 的相关文章

  • 填充体积算法

    我有一个具有一定尺寸长度 宽度 高度的盒子 我有不同长度 宽度 高度的物品 是否有现有的算法可以确定放入盒子中的最佳物品 这称为装箱 切割库存 背包问题 并且是 NP 难问题 一般来说 您只能通过使用启发式方法获得近似解 请参见示例 htt
  • 在 debian Squeeze 上安装 RoR

    有什么方法可以在我的 debian squeeze 上安装 Ruby 1 9 2 或 1 8 7 Rails 3 吗 您可能不想在生产计算机上使用 RVM 它的 PATH 魔力会在不明显的地方 例如 cron 作业 被破坏 然后你就会陷入困
  • 如何从 Ruby 检查具有特定 pid 的进程是否正在运行?

    如果有多种方法 请列出 我只知道一个 但我想知道是否有一种更干净的 Ruby 方式 之间的区别Process getpgid and Process kill方法似乎是当 pid 存在但由另一个用户拥有时发生的情况 Process getp
  • ruby 的 StringIO 类到底是什么?

    我想我明白StringIO有点类似于Java的StringBuffer类 但我不太完全理解 您将如何定义它及其在 Ruby 中的用途 可能的用途 只是希望能够消除我的困惑 no StringIO http ruby doc org stdl
  • Ruby 在带有偏移量的数组中查找

    我正在寻找一种以更简洁的方式在 Ruby 中执行以下操作的方法 class Array def find index with offset offset block offset 1 find block end end offset a
  • 从原点开始在离散 2D 网格上迭代向外螺旋的算法

    例如 这是预期螺旋的形状 以及迭代的每个步骤 y 16 15 14 13 12 17 4 3 2 11 18 5 0 1 10 x 19 6 7 8 9 20 21 22 23 24 其中线条是 x 轴和 y 轴 以下是算法每次迭代 返回
  • 标记(lex?parse?)正则表达式

    使用 Ruby 我想获取一个 Regexp 对象 或表示有效正则表达式的字符串 您的选择 并将其标记化 以便我可以操作某些部分 具体来说 我想采用这样的正则表达式 字符串 regex var w parts foo bar 并创建一个替换字
  • 如何为 bcrypt.hashpw 设置盐?

    salt yhnqazolr123098765 password bcrypt hashpw password salt repeatpassword bcrypt hashpw repeatpassword salt 我在第二行遇到错误
  • BigDecimal 无法强制转换为 BigDecimal

    这应该很简单 但它却爆炸了 有任何想法吗 d BigDecimal new 2 0 YAML load a gt d to yaml TypeError BigDecimal can t be coerced into BigDecimal
  • 将对象数组中的属性映射到另一个数组的更有效的 Ruby 方法?

    我不会在这里重复我的问题 但是有没有更有效的方法来写这个 def recruits names names for r in self referrals do names lt lt r display name end return n
  • 如何从数组中删除空白元素?

    我有以下数组 cities Kathmandu Pokhara Dharan Butwal 我想从数组中删除空白元素并想要以下结果 cities Kathmandu Pokhara Dharan Butwal 有没有类似的方法compact
  • 无需别名的 Ruby YAML 编写

    我正在从 ruby 将数据写入 yaml 文件 并且经常在该文件上添加别名 像 id001 somekey somevalue id001 就我而言 我使用 yaml 文件来aid可读性并将名称添加到文件中的值 因为现有数据只是 没有键的分
  • 由于符号链接错误,无法在 Mac OSX 10.8.1 中安装 ruby​​-1.9.2

    首先 我尝试了常见的rvm安装 rvm安装1 9 2 但是 显示了以下错误 The provided compiler usr bin gcc is LLVM based it is not yet fully supported by r
  • 如何将多边形放入另一个多边形内[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有两个多边形 如下图所示 左边是 粗多边形 右边是 最终多边形 现在 我正在寻找算法来将 最终多边形 拟合到 粗糙多边形 内 并具有
  • Python 旅行商贪婪算法 [关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 因此 我为旅行推销员问题创建了一种排序 并按 x 坐标和 y 坐标进行排序 我正在尝试实施贪婪搜索 但无法做到 此外 每
  • 如何在 gem 的示例脚本中使用 pry-byebug ?

    我正在制作我的第一个 gem 它不是 Rails 应用程序 而是一个带有一些 AI 的 tic tac toe 库 这样我就可以与一个永远不会输的计算机对手比赛 并在可能的情况下强行获胜 现在我正在尝试调试人工智能中的攻击策略 但我似乎无法
  • 为什么 rand() 总是返回相同的数字?

    我在用 兰特 200 在我的 Rails 应用程序中 当我在控制台中运行它时 它总是返回随机数 但如果我在应用程序行中使用它 index rand 200 索引总是相同的号码 为什么会这样以及如何克服这个问题 简单的伪随机数生成器实际上生成
  • 这个函数(for循环)空间复杂度是O(1)还是O(n)?

    public void check 10 for string i list Integer a hashtable get i if a gt 10 hashtable remove i 这是 O 1 还是 O n 我猜测 O n 但不是
  • 如何光栅化旋转矩形(通过 setpixel 在 2d 中)

    我有四个 2d 顶点 A B C D 的旋转矩形 我需要在像素缓冲区中 有效地 光栅化 绘制它 使用 setpixel x y 颜色 怎么做 我正在尝试使用一些代码 例如 convertilg a b c d do up down left
  • 求先递增后递减列表的最大值和最小值

    我尝试用谷歌搜索这个问题 但没有取得太大成功 我确信这个问题或类似问题有一个技术名称 但我似乎找不到答案 给定一个列表L整数 即严格递增 然后严格递减 找到该列表的最大值和最小值 例如 L可能 1 2 3 4 5 4 3 2 or 2 4

随机推荐