代码之家  ›  专栏  ›  技术社区  ›  lumos

从与值匹配的数组开头删除尽可能多的元素,直到数组达到指定大小

  •  3
  • lumos  · 技术社区  · 7 年前

    我试图通过删除与唯一ID匹配的值来修改数组,但一旦数组的前5个值有效(即它们的ID与不需要的ID不匹配),就停止。如果阵列具有计数<=5,那么这就足够了:

    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、我想删除 只有 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 在到达以下位置时完全停止 所有项目[0..4] 已包含5个有效元素。在这种情况下,我希望它在 {"id" => "id08"} ,甚至不检查其余的值(但是,如果 如果需要,请删除

    我知道有一个 delete_if.with_index

    总结一下我的问题:有没有一种方法可以从数组中删除尽可能多的第一个项 array[0..x] 由所需值填充,然后在达到该计数x后停止检查/删除任何剩余项?

    3 回复  |  直到 7 年前
        1
  •  1
  •   Cary Swoveland    7 年前
    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]
    
        2
  •  1
  •   iGian    7 年前

    如果从原始对象中删除,则会得到所有未删除的项目。因此,最好只将所需项目移动到新对象:

    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"}]
    
        3
  •  1
  •   rubish    7 年前

    你可以用 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)