这是一个关于传递引用/值的误解,导致了这个方法无法按预期输出吗?

huangapple go评论65阅读模式
英文:

Is this a pass by reference/value misunderstanding that's having this method fail output as intended?

问题

我正在解决这个问题(在视频中为4小时50分钟):

  • 编写一个名为 all_construct_tabular(target, word_array) 的函数,以返回一个包含所有可以通过连接 word_array 元素构建目标字符串的方式的二维数组。
  • 二维数组的每个元素应代表构建目标的一种组合方式。
  • word_array 的元素可以重复使用。

这是我的测试:

it "returns a 2d array with x4 sub array elements" do
  result = all_construct_tabular('abcdef', ['ab', 'abc', 'cd', 'def', 'abcd', 'ef', 'c'])
  expect(result).to eq([['ab', 'cd', 'ef'], ['ab', 'c', 'def'], ['abc', 'def'], ['abcd', 'ef']])
end

这是我的方法:

def all_construct_tabular(target, word_array)
  table = Array.new(target.length + 1) { [] }
  table[0] = [[]]

  table.each_with_index do |e, i|
    word_array.each do |word|
      if target.slice(i, word.length) == word
        new_combos = table[i].map { |a| a.dup }
        new_combos.each { |a| a << word }
        table[i + word.length] << new_combos
      end
    end
  end
  return table[target.length]
end

这是失败的输出:

expected: [["ab", "cd", "ef"], ["ab", "c", "def"], ["abc", "def"], ["abcd", "ef"]]
            got: [[["ab", "cd", "ef"], "def"], [["ab", "c", "def"], ["abc", "def"]], ["abcd", "ef"]]

我认为问题可能出在第8行,它实际上更新了 table[i] 的值,而我本意只是将更新后的值存储在 new_combos 变量中。而且明显存在数组嵌套的问题。我已经尝试了很长时间,以至于我已经看不出问题所在了,真的很感谢您在我何去何从时给予的指导。提前感谢您。

  • 我达到的一个可行但混乱的解决方案(由许多 object_id 和其他 puts 语句提供):
def all_construct_tabular(target, word_array)
  table = Array.new(target.length + 1) { [] }
  table[0] = [[]]

  table.each_with_index do |e, i|
    word_array.each do |word|
      if target.slice(i, word.length) == word
        new_combos = table[i].map(&:dup)
        new_combos.map(&:flatten!)
        new_combos_with_word = new_combos.map(&:dup)
        new_combos_with_word.each { |e| e.push(word) }
        table[i + word.length] << new_combos_with_word
      end
    end
  end
  return table[target.length].flatten(1)
end
英文:

I'm working on a solution to this problem (4hr50m in this vid):

  • Write a function all_construct_tabular(target, word_array) to return a 2D array containing all of the ways in which the target string can be constructed by concatenating elements of the word_array.
  • Each element of the 2D array should represent one combination that constructs target.
  • Elements of word_array can be reused.

Here's my test:

    it &quot;returns a 2d array with x4 sub array elements&quot; do
      result = all_construct_tabular(&#39;abcdef&#39;, [&#39;ab&#39;, &#39;abc&#39;, &#39;cd&#39;, &#39;def&#39;, &#39;abcd&#39;, &#39;ef&#39;, &#39;c&#39;])
      expect(result).to eq([[&#39;ab&#39;, &#39;cd&#39;, &#39;ef&#39;], [&#39;ab&#39;, &#39;c&#39;, &#39;def&#39;], [&#39;abc&#39;, &#39;def&#39;], [&#39;abcd&#39;, &#39;ef&#39;]])
    end

Here's my method:

def all_construct_tabular(target, word_array)
  table = Array.new(target.length + 1).each.map { Array.new }
  table[0] = [[]]

  table.each_with_index do |e, i|
    word_array.each do |word|
      if target.slice(i, word.length) == word
          new_combos = table[i].map { |a| a &lt;&lt; word }
          table[i + word.length].push(new_combos)      
      end
    end
  end
  return table[target.length]
end

And here's the failing output:

expected: [[&quot;ab&quot;, &quot;cd&quot;, &quot;ef&quot;], [&quot;ab&quot;, &quot;c&quot;, &quot;def&quot;], [&quot;abc&quot;, &quot;def&quot;], [&quot;abcd&quot;, &quot;ef&quot;]]
            got: [[[[&quot;ab&quot;, &quot;abc&quot;, &quot;abcd&quot;], &quot;def&quot;], [[[&quot;ab&quot;, &quot;abc&quot;, &quot;abcd&quot;], &quot;cd&quot;, &quot;c&quot;], &quot;def&quot;]], [[[&quot;ab&quot;, &quot;abc&quot;, &quot;abcd&quot;], &quot;ef&quot;], [[[&quot;ab&quot;, &quot;abc&quot;, &quot;abcd&quot;], &quot;cd&quot;, &quot;c&quot;], &quot;ef&quot;]]]

I think that I may have a situation where line 8 is actually updating the table[i] value, when I'm intending to just store the updated values in the new_combos variable. And I clearly have an array nesting problem. I've been playing with this for so long that I can't see the wood for the trees any longer and would really appreciate any guidance on where I'm going and what I'm doing wrong. Thanks in advance.

– A working, but messy solution that I arrived at (Courtesy of many object_id and other puts statements):

def all_construct_tabular(target, word_array)
  table = Array.new(target.length + 1) { [] }
  table[0] = [[]]

  table.each_with_index do |e, i|
    word_array.each do |word|
      if target.slice(i, word.length) == word
        
        new_combos = table[i].each(&amp;:dup)
        new_combos.map(&amp;:flatten!)
        new_combos_with_word = new_combos.map(&amp;:dup)
        new_combos_with_word.each {|e| e.push(word) }
        table[i + word.length] &lt;&lt; new_combos_with_word
      end
    end
  end
  return table[target.length].flatten(1)
end

答案1

得分: 1

def all_construct_tabular(target, word_array)
  combinations = [[]]

  target.length.times.to_a.product(word_array) do |i, word|
    starting, ending = i, i + word.length
    next unless target[starting...ending] == word

    combinations[ending] ||= []
    combinations[ending].concat(combinations[starting].map { |ary| ary + [word] })
  end

  combinations.last
end

actual = all_construct_tabular("abcdef", ["c", "ab", "abc", "def", "cd", "abcd", "ef"]).sort
expected = [["ab", "cd", "ef"], ["ab", "c", "def"], ["abc", "def"], ["abcd", "ef"]].sort
p actual, expected
puts "Testing: #{actual == expected}"
英文:
def all_construct_tabular(target, word_array)
  table = Array.new(target.length + 1).each.map { [] }
  table[0] = [[]]
  table.each_with_index do |_, i|
    word_array.each do |word|
      if target.slice(i, word.length) == word
        # `&lt;&lt;` modifies the original, but new combinations don&#39;t belong to that array
        new_combos = table[i].map { |a| a + [word] }
        # they belong where these combinations would end
        table[i + word.length].concat(new_combos) # or .push(*new_combos)
      end
    end
  end
  table[target.length]
end

Not sure if there is anything else I can do here, maybe massage some things around:

def all_construct_tabular(target, word_array)
  combinations = [[[]]]

  target.length.times.to_a.product(word_array) do |i, word|
    starting, ending = i, i + word.length
    next unless target[starting...ending] == word

    combinations[ending] ||= []
    combinations[ending].concat(combinations[starting].map { |ary| ary + [word] })
    # [[&quot;abc&quot;, &quot;def&quot;]]          [[&quot;abcd&quot;]]                               [&quot;ef&quot;]
  end

  combinations.last
end

actual = all_construct_tabular(&quot;abcdef&quot;, [&quot;c&quot;, &quot;ab&quot;, &quot;abc&quot;, &quot;def&quot;, &quot;cd&quot;, &quot;abcd&quot;, &quot;ef&quot;]).sort
expected = [[&quot;ab&quot;, &quot;cd&quot;, &quot;ef&quot;], [&quot;ab&quot;, &quot;c&quot;, &quot;def&quot;], [&quot;abc&quot;, &quot;def&quot;], [&quot;abcd&quot;, &quot;ef&quot;]].sort
p actual, expected
puts &quot;Testing: #{actual == expected}&quot;
[[&quot;ab&quot;, &quot;c&quot;, &quot;def&quot;], [&quot;ab&quot;, &quot;cd&quot;, &quot;ef&quot;], [&quot;abc&quot;, &quot;def&quot;], [&quot;abcd&quot;, &quot;ef&quot;]]
[[&quot;ab&quot;, &quot;c&quot;, &quot;def&quot;], [&quot;ab&quot;, &quot;cd&quot;, &quot;ef&quot;], [&quot;abc&quot;, &quot;def&quot;], [&quot;abcd&quot;, &quot;ef&quot;]]
Testing: true

答案2

得分: 0

以下是您要翻译的内容:

如果这对其他人有帮助,我基本上需要的知识来纠正我的代码并回答这个问题在这篇文章中得到了很好的阐述,这是一个三部分系列文章中的第二篇,其中所有这些文章都将帮助任何人理解 Ruby 的对象变异和引用/值传递行为。

英文:

In case this helps anyone else, the knowledge that I essentially needed in order to correct my code and answer this question is well illustrated in this article, the 2nd of a three part series of articles all of which would help anyone getting to grips with Ruby's object mutation and reference / value passing behaviours.

huangapple
  • 本文由 发表于 2023年5月29日 00:06:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76352393.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定