我有{strong>大 order_id
字符串数组:
order_ids = ["1", "2", "5", ...]
我还有一个大数组的order
哈希:
orders = [{order_id: "1", name: "John"}, {order_id: "3", name: "Bob"}, ...]
orders_ids
表示我需要从orders
数组中删除的订单。因此,在上面的示例中,我需要删除{order_id: "1", name: "John"}
。但是数组的大小可以是1M +,所以我需要一种更好的方法,而不是逐个遍历数组。
答案 0 :(得分:2)
除非您计划将数据重新组织成某种树或堆栈(转换时会占用大量内存),否则最好使用#reject
方法进行分割和征服。
orders = [{order_id: "1", name: "John"}, {order_id: "3", name: "Bob"}]
order_ids = ["1", "2", "5"]
orders.reject { |val| order_ids.include?(val[:order_id]) }
输出:
{:order_id=>"3", :name=>"Bob"}
答案 1 :(得分:2)
如果您可以从order_ids
和orders
数组中删除元素,并假设您的orders
数组不包含重复的ID,则可以从两个数组中删除项目以进行制作包含检查更快:
order_ids = %w[1 3 5 7 9]
orders = [
{order_id: "1", name: "Abe"},
{order_id: "2", name: "Bob"},
{order_id: "3", name: "Clara"},
{order_id: "4", name: "Daniel"},
{order_id: "5", name: "Erika"}
]
orders.delete_if do |order|
break if order_ids.empty?
index = order_ids.index(order[:order_id])
order_ids.slice!(index) unless index.nil?
end
p orders #=> [{:order_id=>"2", :name=>"Bob"}, {:order_id=>"4", :name=>"Daniel"}]
p order_ids #=> ["7", "9"]
还可以考虑将order_ids
设为Set,这是进行包含检查的更好选择。此实现可能比前一个更快:
require "set"
# Convert `order_ids` to a set in order to make inclusion checks faster
order_ids = %w[1 3 5 7 9].to_set
# `orders` is the same array as in the previous example
orders.delete_if do |order|
break if order_ids.empty?
order_ids.delete? order[:order_id]
end
p orders #=> [{:order_id=>"2", :name=>"Bob"}, {:order_id=>"4", :name=>"Daniel"}]
p order_ids #=> #<Set: {"7", "9"}>
答案 2 :(得分:0)
如果您愿意花一点额外的内存,可以将其减少为线性时间操作。
order_map = orders.each_with_object({}) {|order, obj| obj[order["order_id"]] = order }
orders.each {|order| order_map.delete order }
filtered_orders = order_map.values