【问题标题】:Delete every other item in the array until only one is left删除数组中的所有其他项目,直到只剩下一个
【发布时间】:2017-10-30 11:26:13
【问题描述】:

我的问题是要求迭代一个项目数组并删除所有其他项目,直到我到达数组的末尾,此时我应该开始向后迭代并继续删除所有其他项目,以此类推,直到只有一个项目是留在数组中。

例如:1,2,3,4,5,会变成 1,3,5,然后是 3

我知道我不应该从原始数组中删除,所以我创建了另一个数组,它只保留所有其他项目,同时减小它的大小,但我无法让它工作并最终导致无限循环。

arr=*(1..10)
s_arr=[]
until s_arr.length==1 
i=0
   while i<arr.length
   s_arr.push(arr[i])
   i+=2
end
   arr=s_arr.reverse
   s_arr=arr
end

谢谢。

【问题讨论】:

  • arr = *(1..10) 的输出是什么? (0...arr.size).each { |index| [index, -index].each { |el| arr.delete_at el } } 不工作吗?
  • [1, 2, 3, 4, 5, 6, 7, 8] 的输出是什么?
  • 你好 Sebastian 这一行 arr = *(1..10) 可以被任何数组替换,比如说 arr = [2,21,1,5,6,12,100,9,17] 之后在这个数组上运行你的代码我剩下两个元素 =>[6, 9] 我只需要一个结束。有什么想法吗?此外,您的代码中的 -index 是如何工作的?我以前从来没有用过减号。谢谢。
  • 为什么要留下两个元素?您的规范说“等等来回直到数组中只剩下一个
  • 你好 Jörg W Mittag - 我不确定我是否在关注你。我只是说,在运行 Sebastian(不是我)建议的代码后,我留下了 2 个元素,而不是只有一个(就像我需要的那样)

标签: arrays ruby


【解决方案1】:

每次迭代,将数组替换为删除所有其他元素的版本

arr = *(1..10)

while arr.length > 1
  arr = arr.select.with_index { |_, i| i % 2 == 0 }.reverse
end

这与您的示例不匹配,但您的示例首先似乎不一致。如果 [1,2,3,4,5] 转到 [1,3,5],那么下一步应该是 [1,5] 而不是 [3]。

【讨论】:

  • 你是绝对正确的。我算错了。你能解释一下下划线吗?我知道它代表一个我们不关心的变量,但是当我们已经用 i%2==0 消除偶数时它如何应用在这里?
  • .select.with_index 将两个参数传递给块:数组元素及其索引。我们只使用索引来确定要保留哪些元素,因此可以安全地忽略第一个参数。
【解决方案2】:

这类似于@Max 的答案,但以递归方式实现。

def last_one_standing(arr)
  return arr.first if arr.size == 1
  last_one_standing arr.select.with_index { |_,i| i.even? }.reverse
end

(1..16).each { |i| puts "1..%d: %d" % [i, last_one_standing((1..i).to_a)] }
1..1:   1
1..2:   1
1..3:   3
1..4:   3
1..5:   1
1..6:   1
1..7:   3
1..8:   3
1..9:   9
1..10:  9
1..11: 11
1..12: 11
1..13:  9
1..14:  9
1..15: 11
1..16: 11      

【讨论】:

    【解决方案3】:

    尝试这样的事情,这样你就可以利用 Ruby 的强大功能

    result = []
    array.each_with_index {|val,idx| result << val if ( idx % 2 == 0)}
    

    【讨论】:

    • 我相信您误解了这个问题,因为您只是返回了一个索引为偶数的元素数组。虽然不直接相关,但您的代码可以简化为 array.select.with_index { |val,idx| idx.even? }
    • @CarySwoveland 感谢您的更正,我喜欢您的建议
    【解决方案4】:

    在你的 ruby​​ 控制台上试试这个:

    arr=*(1..10)
    
    x = (Math::log(arr.length) / Math::log(3)).to_i
    
    3**x
    

    【讨论】:

    • 这需要一些数学上的证明,如果它确实有效的话。
    • 我很佩服您尝试得出一个封闭形式的解决方案,但这是不正确的。例如,如果arr = [1,2,3,4,5]; x = (Math::log(arr.length) / Math::log(3)).to_i # 1; 3**x #=&gt; 3。之后,我们在第一次(从左到右)通过后有[1,3,5],然后在第二次(从右到左)通过后有[1,5],最后是[1]
    【解决方案5】:
    arr=*(1..10)
    
    s_arr=[]
    
    until s_arr.length == 1
      i=0
      while i < arr.length
        s_arr.push(arr[i])
        i+=2
      end
    
      arr=s_arr.reverse
    
      if s_arr.length != 1
        s_arr=[]
      end
    
    end
    

    您的问题是将 s_arr 数组设置为与 arr 相同。然后你必须添加一个条件来告诉它在达到 1 时停止,否则它将变为 0。

    编辑:

    arr=*(1..10)
    
    s_arr=[]
    
    until s_arr.length == 1
      s_arr = []
      i=0
      while i < arr.length
        s_arr.push(arr[i])
        i+=2
      end
      arr=s_arr.reverse
    end
    

    更好的解决方案。

    【讨论】:

    • 非常感谢。很好的解决方案。因此,通过添加条件 / if s_arr.length != 1 / 我们确保一旦它达到 1 的长度就会中断循环?
    • 是的。您也可以将 s_arr 移动到 i=0 所在的位置。
    • 我不理解这个网站上一半的人,这家伙向他的代码寻求帮助,而不是帮助他完全创建其他东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-20
    相关资源
    最近更新 更多