Удалите столько элементов в начале массива, которые соответствуют значению, пока массив не достигнет указанного размера - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь изменить массив, удаляя значения, которые соответствуют уникальному идентификатору, но затем останавливаюсь, как только первые 5 значений массива являются действительными (т.е. их идентификаторы не совпадают с нежелательными).Если массив имеет число <= 5, то этого достаточно: </p>

all_items = [{"id" => "id01"},{"id" => "id02"},{"id" => "id03"},{"id" => "id04"}]
exclude_ids = ["id01","id02"]
all_items.delete_if { |item| exclude_ids.include?(item["id"])}

и желаемый результат равен [{"id" => "id03"},{"id" => "id04"}].

Но в случае, когда общее количество массивов равно> = 5, я хочу удалить только столько первых элементов, сколько необходимо, до тех пор, пока первые 5 элементов (all_items[0..4]) не будут действительными в пределах установленного критерия, а затем прекратить итерации.Если бы я сделал это:

all_items = [{"id" => "id01"},{"id" => "id02"},{"id" => "id03"},{"id" => "id04"},{"id" => "id05"},{"id" => "id06"},{"id" => "id07"},{"id" => "id08"},{"id" => "id09"},{"id" => "id10"}]
exclude_ids = ["id01","id02","id07"]
all_items.delete_if { |item| exclude_ids.include?(item["id"])}
return all_items[0..4]

Я бы получил желаемый результат, [{"id" => "id03"},{"id" => "id04"},{"id" => "id05"},{"id" => "id06"},{"id" => "id08"}].Но я хочу, чтобы delete_if полностью остановился, как только он достигнет точки, где all_items[0..4] уже содержит 5 допустимых элементов.В этом случае я бы хотел, чтобы он ломался после {"id" => "id08"}, и даже не проверял оставшиеся значения.(Однако, если во время работы delete_if общее число падает ниже 5, то оно должно продолжать перебирать все оставшиеся элементы, так как оно попадет в категорию первого фрагмента кода, который я разместил выше, где счетчик<= 5.) ​​</p>

Я знаю, что есть delete_if.with_index, но я не уверен, подходит ли он в этом контексте, тем более что индекс будет смещаться при удалении элементов.

Подводя итог моему вопросу: есть ли способ удалить столько первых элементов из массива, сколько требуется, до тех пор, пока array[0..x] не заполнится желаемыми значениями, а затем прекратить проверку / удаление любых оставшихся элементов после того, как это числох достигнут?

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018
termination_threshold = 5
all_items = (1..20).to_a
  #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
exclusions = [1,2,7]

all_items.reject! do |n|
  break if termination_threshold.zero?
  exclude = exclusions.include? n
  termination_threshold -= 1 if exclude
  exclude
end
  #=> [3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

all_items
  #=> [3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

Следующее можно использовать, если требуется только массив, содержащий первые termination_threshold допустимые элементы all_items:

all_items.each_with_object([]) do |e,arr|
  arr << e unless exclusions.include?(e)
  break arr if arr.size == termination_threshold
end
  #=> [3, 4, 5, 6, 8]
0 голосов
/ 20 ноября 2018

Вы можете использовать Enumerator :: Lazy для достижения того, что вы хотите:

all_items = [{"id" => "id01"},{"id" => "id02"},{"id" => "id03"},{"id" => "id04"},{"id" => "id05"},{"id" => "id06"},{"id" => "id07"},{"id" => "id08"},{"id" => "id09"},{"id" => "id10"}]
exclude_ids = ["id01","id02","id07"]
all_items.lazy.reject {|item| exclude_ids.include?(item['id']) }.first(5)
0 голосов
/ 20 ноября 2018

Если вы удалите из исходного объекта, вы получите все элементы, которые не были удалены.Итак, я думаю, что лучше переместить только нужные элементы в новый объект:

all_items.each_with_object([]) { |item, ary| ary << item if !exclude_ids.include?(item["id"]) and ary.size < 5 }

#=> [{"id"=>"id03"}, {"id"=>"id04"}, {"id"=>"id05"}, {"id"=>"id06"}, {"id"=>"id08"}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...