【问题标题】:change contents of shallow copied array of strings in ruby更改 ruby​​ 中浅拷贝字符串数组的内容
【发布时间】:2013-04-25 15:52:37
【问题描述】:

假设我在 ruby​​ 中创建了以下数组:

a = ["apple", "cherry"]
b = a.dup

这里,b 是 a 的浅拷贝。所以如果我这样做:

a.each{|fruit| fruit << " pie"}

我得到 a 和 b 都等于 ["apple pie", "cherry pie"]。那里没问题。但是假设我改变了 b 的一个元素:

b[1] = "blueberry"

并发出相同的“每个”命令。现在 b 是 ["apple pie", "blueberry"],因为 a[0] 和 b[0] 是相同的字符串,但 a[1] 和 b[1] 是不同的字符串。我可以在 a 和 b 上运行命令,但是 b 是 ["apple pie pie", "blueberry pie"],因为我已经对同一个字符串运行了两次追加操作。

有没有办法就地修改a和b的所有字符串,不重复。在这个简单的示例中,我可以测试子字符串“pie”,但这不适用于其他类型的更改(例如删除第一个字符)。

我尝试创建一个包含所有字符串的集合,以便每个字符串都是唯一的;但似乎集合创建复制了字符串,因此无法就地修改它们。有没有办法测试两个字符串在内存中是否相同?我用谷歌搜索过,但什么也没找到。

它的应用是我有很大的字符串数组,我“复制”它们来创建它们的历史。现在我想对整个历史记录应用更改,而不是双重应用(或三重等)更改。

【问题讨论】:

    标签: ruby arrays string shallow-copy


    【解决方案1】:

    我不了解您的用例;我怀疑你让事情变得比他们需要的更复杂。

    有没有办法测试两个字符串在内存中是否相同?

    Object#object_id 是你要找的。​​p>

    有没有办法原地修改a和b的所有字符串,不重复?

    您可以保留一组并非所有的object_ids,类似于您已经尝试过的。您可以使用ObjectSpace#_id2ref 检索字符串。像这样的:

    require 'set'
    
    set = Set.new
    a = ["apple", "cherry"]
    b = a.dup
    b[1] = "blueberry"
    
    # Collect unique string objects
    a.each{|s| set << s.object_id}
    b.each{|s| set << s.object_id}
    
    # Make pie with each unique string object
    set.each{|id| ObjectSpace._id2ref(id) << " pie"}
    
    a
    # => ["apple pie", "cherry pie"]
    b
    # => ["apple pie", "blueberry pie"]
    

    不过,这对我来说似乎有点疯狂。同样,我认为可能有更好的方法来做你想做的事情,但根据提供的信息很难判断。

    【讨论】:

    • 这正是我想要的!谢谢!
    • 至于用例:我有一个字符串数组作为我的主要数据结构。随着时间的推移,我对字符串数组进行了更改。我想存储这些更改的历史记录。为此,我使用“dup”来创建包含相同字符串的新数组。然后当我改变一个字符串时,我只改变那个字符串。这节省了内存,因为我不必存储所有那些重复的字符串。
    • 酷,乐于助人。我仍然无法想象想要那样的东西,但不用担心。如果它可以满足您的需求,那就太好了。我想让我感到困惑的主要事情是创建一个浅拷贝作为历史,然后在更改共享字符串时重写历史。就像损坏的写时复制。但听起来你理解你正在做的事情的含义并且它对你有用,所以一切都很好。顺便说一句,如果您认为它充分解决了您的问题,您应该将其设置为您接受的答案,听起来确实如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 2016-12-03
    • 1970-01-01
    • 2021-11-26
    • 2012-04-12
    相关资源
    最近更新 更多