Ruby 为什么数组的索引重复打印出来是2?

Ruby 为什么数组的索引重复打印出来是2?,ruby,Ruby,我正在处理这个函数: 它应该接收一个数组并将其与给定的单词匹配,以查看该单词是否可以由给定的字符串数组组成 我添加了两行注释,因为我想看看for循环是如何工作的 def canformword(arr,word) arrword = word.chars arrleft = arr flag = true for i in 0...arrword.size ch = arrword[i] # puts arrword[i] if !arrleft.incl

我正在处理这个函数:

它应该接收一个数组并将其与给定的单词匹配,以查看该单词是否可以由给定的字符串数组组成

我添加了两行注释,因为我想看看for循环是如何工作的

def canformword(arr,word)
  arrword = word.chars
  arrleft = arr
  flag = true
  for i in 0...arrword.size
    ch = arrword[i]
    # puts arrword[i]
    if !arrleft.include?(ch)
      flag = false
      break
    else
      ind = arrleft.index(ch)
      # puts ind
      arrleft.delete_at(ind)
    end
  end
  if flag
    puts 'can form word'
  else
    puts 'can not form word'
  end
end

canformword(['y','b','z','e','a','u','t'], 'beauty')
canformword(['r','o','u','g','h'], 'tough')
当我取消注释这两行时,输出如下:

为什么输出会重复打印索引2?我想它会打印出我左边数组中每个字母的索引,而不是重复地吐出2

我理解它打印出来的1,因为这是b的索引,但其余的对我来说很奇怪

b
1
e
2
a
2
u
2
t
2
y
0
can form word
t
can not form word

听到一个更好的实现

def can_form_word?(chars_array, word)
   (word.chars - chars_array).empty?
end
就这些

这里是另一个Ruby方式的实现。因为你的代码就像C。我已经写了三年多的Ruby代码了,我从来没有用过循环


听到一个更好的实现

def can_form_word?(chars_array, word)
   (word.chars - chars_array).empty?
end
就这些

这里是另一个Ruby方式的实现。因为你的代码就像C。我已经写了三年多的Ruby代码了,我从来没有用过循环


这是因为您正在删除位于indarrleft位置的字符。删除\u atind;所以每次数组字符向左移动一个单元格。 现在,由于你所有的字母‘e’、‘a’、‘u’、‘t’、‘y’都是按顺序排列的,所以它连续显示为2,2,2,2。 现在看看“y”;它位于位置0;因此,在末尾打印0

因此,问题在于您正在删除位置“ind”处的字符


所以,要做到这一点,你只需做一件事;找到时不要删除字符,而是将其替换为某些数值,如“0”。

这是因为您正在删除位于indarrleft位置的字符。删除\u atind;所以每次数组字符向左移动一个单元格。 现在,由于你所有的字母‘e’、‘a’、‘u’、‘t’、‘y’都是按顺序排列的,所以它连续显示为2,2,2,2。 现在看看“y”;它位于位置0;因此,在末尾打印0

因此,问题在于您正在删除位置“ind”处的字符


所以,要做到这一点,你只需做一件事;找到时不要删除字符,而是将其替换为某些数值,如“0”。

由于要从数组中删除元素,因此多次获得2。在这种情况下,您每次都删除第二个元素,因此在下一次迭代中,下一个字符再次获取索引2。

您多次获得2,因为您正在从数组中删除元素。在这种情况下,您每次删除第二个元素,以便下一个字符在下一次迭代中再次使用索引2。

问题 如果要从数组中删除索引2和3,则需要按降序删除它们,因为删除索引2会修改索引3:

array = %w(a b c d e)
array.delete_at(3)
array.delete_at(2)
p array
#=> ["a", "b", "e"]

解决方案 对于您的代码,您只需要替换

arrleft.delete_at(ind)

可供替代的 由于您考虑了字符数,因此这里是以前版本的修改版本:

问题 如果要从数组中删除索引2和3,则需要按降序删除它们,因为删除索引2会修改索引3:

array = %w(a b c d e)
array.delete_at(3)
array.delete_at(2)
p array
#=> ["a", "b", "e"]

解决方案 对于您的代码,您只需要替换

arrleft.delete_at(ind)

可供替代的 由于您考虑了字符数,因此这里是以前版本的修改版本:


代码中的一个错误是0…arrword.size中的i。你不能从0到arrwords.size。假设数组有5个元素。从0到5,你会数到6个元素,明白吗?应该是0…arrword.size-1中的i。此外,您真的必须使用for循环吗?这可以用“Ruby方式”缩短。啊,我明白了,谢谢你的洞察力。我之所以使用for循环,是因为我只想练习我的Ruby不客气。请注意Nafaa Boutefer给出的答案中有两个重要的Ruby方法。1测试某物并返回真或假的方法通常以问号结尾。这使事情更具可读性,因为这些方法确实是问题;2命名你的方法能形成单词吗?比canformword好吗?。还有一个可读性问题。@EddeAlmeida 0…arrword.size是否正确请注意这三个点。或者,您可以编写0..arrword.size-1。OP:如果你想使用for循环,你应该把它写成arrword中的for i,那么i是数组中的元素。无论如何首先不应该使用for循环。代码中的一个错误是for i in 0…arrword.size。你不能从0到arrwords.size。假设数组有5个元素。从0到5,你会数到6个元素,明白吗?应该是0…arrword.size-1中的i。此外,您真的必须使用for循环吗?这可以用“Ruby方式”缩短。啊,我明白了,谢谢你的洞察力。我之所以使用for循环,是因为我只想练习我的Ruby不客气。请注意Nafaa Boutefer给出的答案中的两个重要问题
我不知道怎么做。1测试某物并返回真或假的方法通常以问号结尾。这使事情更具可读性,因为这些方法确实是问题;2命名你的方法能形成单词吗?比canformword好吗?。还有一个可读性问题。@EddeAlmeida 0…arrword.size是否正确请注意这三个点。或者,您可以编写0..arrword.size-1。OP:如果你想使用for循环,你应该把它写成arrword中的for i,那么i是数组中的元素。无论如何首先,您不应该使用for循环。您是否假设可以重复使用chars_数组中的字符?在这种情况下,用于测试的OP代码会发生什么变化:canformword['y','b','z','e','a','u','t','beauty'?它失败了,因为我们在chars_数组中有“z”,它不会出现在beauty中,然后是word.chars-chars_数组.empty?如果结果为真,则显然为假。OP从未说过chars_数组应该只包含单词中使用的字母。如果给定的单词可能由这些字母组成,则返回true。@EddeAlmeida'beauty'。chars-['y','b','z','e','a','u','t']返回[]非常抱歉。事实上,我想的正好相反,chars_数组-word.chars。我将删除我的否决票。您是否假设可以重用chars_数组中的字符?在本例中,用于测试的OP对您的代码会有什么影响:canformword['y','b','z','e','a','u','t','beauty'?它失败了,因为我们在chars_数组中有“z”,它不会出现在beauty中,然后是word.chars-chars_数组.empty?如果结果为真,则显然为假。OP从未说过chars_数组应该只包含单词中使用的字母。如果给定的单词可能由这些字母组成,则返回true。@EddeAlmeida'beauty'。chars-['y','b','z','e','a','u','t']返回[]非常抱歉。事实上,我想的正好相反,chars_数组-word.chars。我将取消我的否决票。
class Array
  def count_by
    each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
  end

  def subset_of?(superset)
    superset_counts = superset.count_by
    count_by.all? { |k, count| superset_counts[k] >= count }
  end
end

def can_form_word?(chars, word)
  word.chars.subset_of?(chars)
end

p can_form_word?(['y','b','z','e','a','u','t'], 'beauty')
#=> true
p can_form_word?(['y','b','z','e','u','t'], 'beauty')
#=> false
p can_form_word?(['a', 'c', 'e', 'p', 't', 'b', 'l'], 'acceptable')
#=> false
p ('acceptable'.chars - ['a', 'c', 'e', 'p', 't', 'b', 'l']).empty?
#=> true