好的,所以我有这个数组。较大数组中的每个数组都非常相同,十个特定值。如果我在位置3处的值是一个特定的值,那么我想迭代较大数组中其余的剩余数组,并查看位置0、1和2匹配的前3个值。如果它们匹配,我想删除原始数组。我很难过,也许有一种简单的方法?我敢肯定,我对整个编码的内容=)提前感谢您的帮助。...
这是我在的地方:
@projectsandtrials.each do |removed|
if removed[3] == ["Not Harvested"]
@arraysforloop = @projectsandtrials.clone
@arraysforloop1 = @arraysforloop.clone.delete(removed)
@arraysforloop1.each do |m|
if (m & [removed[0], removed[1], removed[2]]).any?
@projectsandtrials.delete(removed)
end
end
end
end
让我们看看您的情况:
@projectsandtrials.each do |removed|
// some logic, yada yada
@projectsandtrials.delete(removed)
end
您不能仅仅从迭代的阵列中删除内容。至少直到完成迭代为止。您应该使用的是一种过滤方法,例如reject
而不是each
。
因此,当使用拒绝时,您应该只是返回true而不是删除那里。
我在迭代阵列时会这样考虑。
我是否希望该数组保持相同的大小并具有相同的内容?使用每个。
我是否希望该数组的大小相同,但内容不同?使用地图。
我是否希望该数组小于或等于当前大小?使用选择或拒绝。
我是否希望它最终成为一个值?使用降低。
代码
def prune(arr, val)
arr.values_at(*(0..arr.size-4).reject { |i| arr[i][3] == val &&
arr[i+1..i+3].transpose[0,3].map(&:uniq).all? { |a| a.size==1 } }.
concat((arr.size-3..arr.size-1).to_a))
end
示例
arr = [ [1,2,3,4,0],
[3,4,5,6,1],
[3,4,5,4,2],
[3,4,5,6,3],
[3,4,5,6,4],
[3,4,0,6,5],
[2,3,5,4,6],
[2,3,5,5,7],
[2,3,5,7,8],
[2,3,5,8,9],
[2,3,5,7,0]
]
请注意,arr
的元素(数组)的最后值是连续的。这是为了帮助您确定已删除的prune(arr, 4)
(下)的元素。
prune(arr, 4)
# => [[3, 4, 5, 6, 1],
# [3, 4, 5, 4, 2],
# [3, 4, 5, 6, 3],
# [3, 4, 5, 6, 4],
# [3, 4, 0, 6, 5],
# [2, 3, 5, 5, 7],
# [2, 3, 5, 7, 8],
# [2, 3, 5, 8, 9],
# [2, 3, 5, 7, 0]]
说明
索引0
和6
的数组尚未包含在返回的数组中。
arr[0]
([1,2,3,4,0]
)尚未包括在内,因为arr[0][3] = val = 4
和arr[1]
,arr[2]
和arr[3]
全部开始[3,4,5]
。
arr[6]
([2,3,5,4,6]
)尚未包括在内,因为arr[6][3] = 4
和arr[7]
,arr[8]
和arr[9]
都开始[2,3,5]
。
arr[2]
([3,4,5,5,2]
)被包括在内,因为arr[2][3] = 4
,arr[3][0,3]
,arr[4][0,3]
和arr[5][0,3]
并非全部相等(即arr[5][2] = 0
)。
请注意,arr
的最后三个要素将始终包含在返回的数组中。
现在让我们检查计算。首先考虑以下。
arr.size
#=> 11
a = (0..arr.size-4).reject { |i| arr[i][3] == val &&
arr[i+1..i+3].transpose[0,3].map(&:uniq).all? { |a| a.size==1 } }
#=> (0..7).reject { |i| arr[i][3] == val &&
arr[i+1..i+3].transpose[0,3].map(&:uniq).all? { |a| a.size==1 } }
#=> [1, 2, 3, 4, 5, 7]
考虑i=0
的reject
的块计算(Ressect val=4
)。
arr[i][3] == val && arr[i+1..i+3].transpose[0,3].map(&:uniq).all? {|a| a.size==1 }}
#=> 4 == 4 && arr[1..3].transpose[0,3].map(&:uniq).all? { |a| a.size==1 }
#=> [[3,4,5,6,1],
# [3,4,5,4,2],
# [3,4,5,6,3]].transpose[0,3].map(&:uniq).all? { |a| a.size==1 }
#=> [[3, 3, 3],
# [4, 4, 4],
# [5, 5, 5],
# [6, 4, 6],
# [1, 2, 3]][0,3].map(&:uniq).all? { |a| a.size==1 }
#=> [[3, 3, 3],
# [4, 4, 4],
# [5, 5, 5]].map(&:uniq).all? { |a| a.size==1 }
#=> [[3], [4], [5]].all? { |a| a.size==1 }
#=> true
意味着arr[0]
将被拒绝;即,未包含在返回的数组中。其余的块计算(对于i=1,...,10
)是相似的。
我们已经计算出
a #=> [1, 2, 3, 4, 5, 7]
是arr
所有元素的索引,除了要保留的最后一个3
。在a
中,我们添加了arr
的最后三个元素的索引。
b = a.concat((arr.size-3..arr.size-1).to_a)
#=> a.concat((8..10).to_a)
#=> a.concat([8,9,10])
#=> [1, 2, 3, 4, 5, 7, 8, 9, 10]
最后,
arr.values_at(*b)
返回示例中给出的数组。
您的代码段似乎还不错,尽管有几件事要注意:
-
@arraysforloop.clone.delete(removed)
删除了removed
数组的所有出现(不仅是第一个)。例如。[1,2,3,1] .DELETE(1)会给您[2,3]。您可以使用@projectsandtrials
和DELETE_AT方法的迭代器来修复它。 -
delete
方法返回您传递给它的同一参数(或者如果找不到匹配的话,则无需返回)。因此,@arraysforloop1 = @arraysforloop.clone.delete(removed)
使您的@arraysforloop1
仅包含删除的数组的元素!删除作业可以为您节省。 -
我没有理由拥有两个克隆的阵列
@arraysforloop
和@arraysforloop1
,因为以后不使用前一个。可能是我们可以省略其中之一吗? -
@projectsandtrials.delete(removed)
只要您现在迭代相同的数组,就会使您处于一个奇怪的状态。这可能会导致您在删除一个元素后错过了正确的下一个元素。这是一个简单的片段来说明行为:> a = [1,2,3] > a.each{|e, index| puts("element is: #{e}"); a.delete(1);} element is: 1 element is: 3
如您所见,删除元素
1
后,循环直接移至element3
,省略了2
(因为它成为数组中的第一个元素,并且算法认为它已经已经处理过)。
使它不那么混乱的可能性之一就是将其拆分为一束方法。这是一个选项:
def has_searched_element? row
# I leave this method implementation to you
end
def next_rows_contain_three_duplicates?(elements, index)
# I leave this method implementation to you
end
def find_row_ids_to_remove elements
[].tap do |result|
elements.each_with_index do |row, index|
condition = has_searched_element?(row) && next_rows_contain_three_duplicates?(elements, index)
result << index if condition
end
end
end
row_ids_to_remove = find_row_ids_to_remove(@projectsandtrials)
# now remove all the elements at those ids out of @projectsandtrials