delete_atは単一のインデックスしか取りません。組み込みのメソッドを使用してこれを達成するには良い方法はありますか? セットである必要はなく、インデックスの配列であってもかまいません。インデックスの集合に基づいて配列の内容を削除します
arr = ["a", "b", "c"]
set = Set.new [1, 2]
arr.delete_at set
# => arr = ["a"]
delete_atは単一のインデックスしか取りません。組み込みのメソッドを使用してこれを達成するには良い方法はありますか? セットである必要はなく、インデックスの配列であってもかまいません。インデックスの集合に基づいて配列の内容を削除します
arr = ["a", "b", "c"]
set = Set.new [1, 2]
arr.delete_at set
# => arr = ["a"]
ワンライナー:
arr.delete_if.with_index { |_, index| set.include? index }
'_'アンダースコアを探すのは難しいのでちょっとメモしてください - それはプレースホルダですこれは単にインデックスを無視する場合によく使用されます。 '_'は有効な変数ですが、コード行には何も進んでいません。 – Mirv
これを試してみてください:
arr.reject { |item| set.include? arr.index(item) } # => [a]
それは私が考えて、少し醜いです;)たぶん誰かがよりよい解決策を提案しますか?
私の問題のための簡単な解決策、他は失敗しました! – dariush
Arrayクラスを再オープンし、新しいメソッドを追加します。
class Array
def delete_at_multi(arr)
arr = arr.sort.reverse # delete highest indexes first.
arr.each do |i|
self.delete_at i
end
self
end
end
arr = ["a", "b", "c"]
set = [1, 2]
arr.delete_at_multi(set)
arr # => ["a"]
これはもちろん、クラスを再オープンしたくない場合は、スタンドアロンの方法として記述することができます。索引が逆順になっていることを確認することが重要です。そうしないと、後で削除されるはずの配列内の要素の位置が変更されます。
+1ですが、* delete_at_indices *はより良い名前になります:delete_atの可読性は維持されますが、それでも複数のインデックスが必要であることは明らかです。あなたが「3時に削除」または「インデックス3,5、および7で削除する」と言っても、「マルチ3,5,7で削除」とは言っていません。 (そしてもちろん、 "索引"という言葉を使用することを嫌う人のために、別名* delete_at_indexes *;)があるかもしれません。 – iconoclast
機能アプローチ:
class Array
def except_values_at(*indexes)
([-1] + indexes + [self.size]).sort.each_cons(2).flat_map do |idx1, idx2|
self[idx1+1...idx2] || []
end
end
end
>> ["a", "b", "c", "d", "e"].except_values_at(1, 3)
=> ["a", "c", "e"]
は、必ずしもその場で修正しなければなりませんか? – tokland
別の配列を使うのではなく、Set.newでSet型を使用して、一意性を保証していますか? – Mirv