2011-11-01 7 views
6

delete_at solo toma un índice único. ¿Cuál es una buena manera de lograr esto usando métodos integrados? No tiene que ser un conjunto, puede ser una matriz de índices también.Eliminar contenidos de la matriz según un conjunto de índices

arr = ["a", "b", "c"] 
set = Set.new [1, 2] 
arr.delete_at set 
# => arr = ["a"] 
+0

debe ser necesariamente una modificación en el lugar? – tokland

+0

Supongo que está utilizando el tipo Establecer en 'Set.new' para garantizar la exclusividad, en lugar de simplemente usar otra matriz. – Mirv

Respuesta

12

de una sola línea:

arr.delete_if.with_index { |_, index| set.include? index } 
+0

Solo una nota, ya que es difícil buscar el símbolo de subrayado '_' - es un marcador de posición eso se usa comúnmente si simplemente ignoras el índice. El '_' es una variable válida, pero la línea de código no funciona con nada. – Mirv

1

Prueba esto:

arr.reject { |item| set.include? arr.index(item) } # => [a] 

Es un poco feo, creo;) Tal vez alguien sugerir una mejor solución?

+0

¡Una solución simple para mi problema, mientras que otros fallaron! – dariush

4

Vuelva a abrir la clase Array y añada un nuevo método para esto.

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"] 

Esto, por supuesto, puede escribirse como un método independiente si no desea volver a abrir la clase. Asegurarse de que los índices estén en orden inverso es muy importante, de lo contrario cambiará la posición de los elementos más adelante en la matriz que se supone que se eliminarán.

+0

+1, pero * delete_at_indices * sería un nombre mejor: conserva la legibilidad de delete_at, pero todavía hace obvio que toma varios índices. En cuanto a la legibilidad, podría decir "eliminar a 3" o "eliminar en los índices 3, 5 y 7", pero no diría "eliminar en multi 3, 5 y 7". (Y por supuesto, para aquellos que no son pedantes sobre el uso de la palabra "índices", podría haber un alias * delete_at_indexes *;) – iconoclast

0

enfoque funcional:

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"] 
Cuestiones relacionadas