skus = [
{:size=>"L(成人)", :color=>"灰色", :outer_id=>"BML21B0603000L", :quantity=>"3"},
{:size=>"M(成人)", :color=>"灰色", :outer_id=>"BML21B0603000M", :quantity=>"3"},
{:size=>"S(成人)", :color=>"灰色", :outer_id=>"BML21B0603000S", :quantity=>"2"},
{:size=>"XL(成人)", :color=>"灰色", :outer_id=>"BML21B060300XL", :quantity=>"1"}
]
skus.each do |sku|
Sku.create(sku) # 创建
skus.delete(sku)
end
=> [{:size=>"M(成人)", :color=>"灰色", :outer_id=>"BML21B0603000M", :quantity=>"3"}, {:size=>"XL(成人)", :color=>"灰色", :outer_id=>"BML21B060300XL", :quantity=>"1"}]
经常通过数组,进行数据插入,为了检测业务逻辑中的各种遗漏,每成功后会从原数组中做 delete 操作,但发现会直接影响 each 的循环次数,以至于更大的遗漏;
大家有什么好的方法吗?
先 dup 一下啊
a=[1,2,3,4,5,6,7,8,9]
b = a.dup
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
a.each do |i|
b.delete(i)
end
=> [2, 4, 6, 8]
我现在的做法是:
def process_sync(skus)
skus_data = {}
skus.each do |sku|
key = sku['num_iid']
skus_data[key] = [] unless skus_data.has_key?(key)
skus_data[key] << sku
end
item_ids = skus_data.keys
Item.any_in(num_iid: item_ids).each do |item| # 商品
skus = skus_data[item.num_iid]
updated = [] # 更新
unchanged = [] # 无变化
item.skus.each do |sku|
skus.each do |data|
if sku.sku_id == data['sku_id']
if data['modified'] > sku.modified_at
sku.update_attributes(data)
updated << data
else
unchanged << data
end
end
end
end
created = skus - ( updated + unchanged ) # 新增
unless created.empty?
created.each do |data|
item.skus.create(data)
end
end
puts "Sku.process_sync==============(#{item.num_iid})==============提示"
puts "本次同步,共获取 #{skus.count} 单品,其中 新增 #{created.count},更新 #{updated.count},无变化 #{unchanged.count} 单品"
skus_data.delete(item.num_iid)
end
unless skus_data.empty?
puts "Sku.process_sync============================提示"
puts skus_data
end
end
‘’‘ a=[1,2,3,4,5,6,7,8,9] => [1, 2, 3, 4, 5, 6, 7, 8, 9] a.each do |i| a.delete(i) end => [2, 4, 6, 8]
’‘’ 我初学 ruby,我说下我的看法,首先咱们看下 each 和 map 的区别,each 后的代码块不管处理啥都会返回原数组,Map 将返回处理过的数组。
好,我们看下代码,第一个元素是 1,你操作了删除 1,那么这个时候 a=[2,3,4,5,6,7,8,9],each 内代码块以为 a 的索引应该到 a[1] 也就是第二个,那么就把 3 删掉,以此下去。
所以看到的结果是【2,4,6,8】,这个结果就是 现在 a 数组的原始数据了。
我是这么理解的。 另外要防止这样的情况,有很多办法啊,比如你自己定义方法然后携带 Block,最简单就是 复制一份 a 数组,然后从 a 开始 循环,删除 B 数组 ''' a=[1,2,3,4,5,6,7,8,9] b=a => [1, 2, 3, 4, 5, 6, 7, 8, 9] a.each do |i| b.delete(i) end '''
4L 的作法也对的
所有的语言都要尽量避免在循环内部修大幅改循环继续或停止的算法和条件。 C/Java 的循环基本上就是 ++ 或者 --
如果一个 loop 写成这样,就很难搞
for(int i = 0; i < 100;i++){
int x,y,z
if( ... ){
....
i+= 2x-y+z^
}else{
.....
i-= x+3y
}
i-=2
}
你的例子中,a 内部的元素就是循环继续或停止的条件。
不然很头疼的,比如跟你的例子相似,改一个地方就麻烦了:
a=[1,2,3,4,5,6,7,8,9]
a.each do |i|
a << i
end
飘过..... 遍历老数组,把要删的东西,先放到一个新数组里面, 然后遍历新数组,删除老数组的元素。 不过这样性能比较弱。
我觉得更好的思路是, 把你想要的东西,放到一个新数组里面, 而不是删除你不想要的东西。