Ruby reverse.each_with_index 和 delete_at 导致最新 Ruby/Rails 出现问题 [英] Ruby reverse.each_with_index and delete_at causing problems in latest Ruby/Rails

查看:37
本文介绍了Ruby reverse.each_with_index 和 delete_at 导致最新 Ruby/Rails 出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我很清楚在迭代块中删除项目的危险(这是反向循环),我知道 Matz 提到了一些关于迭代中导致稳定性问题的突变,但我似乎无法弄清楚这个出来了.

So, I'm well aware of the perils of removing items in an iteration block (this is looping in reverse), and I know Matz mentioned something about mutations in iterations causing stability problems, but I can't seem to figure this one out.

这个例子有点复杂,我不确定即使解决它也会完全复制这个例子,但我必须尝试.

This example is a little convoluted and I'm not sure even solving it will replicate the example exactly, but I'll have to try.

arr1 = [1, 2, 3, 4, 5]
arr2 = [3, 4, 5]
puts arr1.inspect
puts arr2.inspect
arr2.each do |i|
  arr1.reverse.each_with_index do |j, index|
    if i == j
      arr1.delete_at(index)
    end
  end
end
puts arr1.inspect
puts arr2.inspect

输出:

[1, 2, 3, 4, 5]
[3, 4, 5]
[4, 5]
[3, 4, 5]

应该什么时候:

[1, 2, 3, 4, 5]
[3, 4, 5]
[1, 2]
[3, 4, 5]

将 delete_at(index) 更改为 delete(j) 解决了这个问题,但是当数组是对象时不起作用.我还将对象复制到临时数组以使事情变得更加复杂.

changing delete_at(index) to delete(j) fixes this, but didn't work when the array was objects. I'm also copying the objects to a temp array to make matters more complicated.

在我的现实生活场景中,我有两个数组,其中填充了不同类型的 Model 对象,但共享一个公共属性(可能在这里使用连接,但我试图避免使用特殊的连接表).我想要的是删除 array1 中在 array2 中具有公共属性的任何对象.我尝试了许多不同的方法,但都没有解决方案……太多了,无法放在这里.

In my real life scenario, I have two arrays filled with Model objects of different type but share a common attribute (could probably use a join here, but I'm trying to avoid a special join table). What I want is to remove any objects in array1 that have a common attribute in array2. I've tried a number of different things with no solution... too many to put here.

@arr1 = []
original_arr1 = Model1.where(...)
original_arr1.each { |original| @arr1 << original.dup }
@arr2 = Model2.where(...)
@arr2.each do |object1|
  @arr1.reverse.each_with_index do |object2, index|
    if object1.color == object2.color
      @arr1.delete_at(version_index)
    end
  end
end

如果没有上面的额外复制,模型关联将保留,我最终会从表中删除记录,这不应该发生.这只是一个临时列表.这似乎是一个愚蠢的问题,我在它上面花了太多时间.

Without the extra copying above, the Model associations will remain and I will end up deleting the record from the table, which should not happen. It's just a temporary list. This seems like a stupid problem and I've spent way too much time on it.

推荐答案

您正在使用反向索引进行删除,但从原始数组中删除.

You're deleting using the reversed index, but from the original array.

要获得真正的"索引,而不是从数组末尾开始计数,您需要将其翻转:

To get the "real" index, instead of one counting from the end of the array, you need to flip it around:

arr1.delete_at(-index - 1)

<小时>

...但您几乎肯定应该使用 拒绝!delete_if 代替:

require "set"

unwanted_colors = @arr2.map(&:color).to_set
@arr1.reject! { |el| unwanted_colors.include?(el.color) }

这篇关于Ruby reverse.each_with_index 和 delete_at 导致最新 Ruby/Rails 出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆