为什么重复打印数组的索引为2?

时间:2017-01-17 11:27:19

标签: 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.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?我认为它会在我的arrleft数组中打印出每个字母的索引而不是反复吐出2!

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

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

4 个答案:

答案 0 :(得分:3)

听到更好的实施

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

就是这样。

这里是Ruby方式的另一种实现方式。因为您的代码就像C。我已经编写Ruby代码超过三年了,我从未使用for循环。

def canformword(chars,word)
    word.each_char do |char|
       puts char
       if !chars.include?(char)
         return false # or puts "Can't form word"
       end
    end
    true # or puts "Can form word"
end

答案 1 :(得分:2)

这是因为你要删除位置ind的字符(arrleft.delete_at(ind));所以每次数组字符都移动一个单元格。 现在,所有的信件都是'' a'' u'''' y'按顺序排列,以便连续显示2,2,2,2。 现在看看' y;它位于0;所以0结尾打印。

所以问题是因为你要删除位置' ind'。

的字符

所以,要做到这一点,你可以做一件事;不要在找到时删除字符,而是用一些数字值替换它,例如' 0'。

答案 2 :(得分:2)

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

答案 3 :(得分:1)

问题

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

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

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

解决方案

对于您的代码,您只需要替换

arrleft.delete_at(ind)

arrleft[ind] = nil

替代

由于您考虑了字符数,因此这是之前answer的修改版本:

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