英文:
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 "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
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 << word }
          table[i + word.length].push(new_combos)      
      end
    end
  end
  return table[target.length]
end
And here's the failing output:
expected: [["ab", "cd", "ef"], ["ab", "c", "def"], ["abc", "def"], ["abcd", "ef"]]
            got: [[[["ab", "abc", "abcd"], "def"], [[["ab", "abc", "abcd"], "cd", "c"], "def"]], [[["ab", "abc", "abcd"], "ef"], [[["ab", "abc", "abcd"], "cd", "c"], "ef"]]]
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(&: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
答案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
        # `<<` modifies the original, but new combinations don'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] })
    # [["abc", "def"]]          [["abcd"]]                               ["ef"]
  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}"
[["ab", "c", "def"], ["ab", "cd", "ef"], ["abc", "def"], ["abcd", "ef"]]
[["ab", "c", "def"], ["ab", "cd", "ef"], ["abc", "def"], ["abcd", "ef"]]
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论