Найти и заменить в многомерном массиве Ruby - PullRequest
2 голосов
/ 21 мая 2011

Существует ли элегантный способ найти и заменить любые целые числа, превосходящие 3 (как пример), в многомерном массиве?Массив может иметь размерность 1, 2, 3 или более.Просто пример такого массива:

[ [ [ 3, 3, 5 ], 
    [ 4, 3, 3 ] ], 
  [ [ 3, 2, 3 ], 
    [ 0, 3, 8 ] ] ]

Я бы хотел сделать это без сглаживания массива.

Ответы [ 3 ]

5 голосов
/ 21 мая 2011

Следуя идее sepp2k, возможна реализация:

class Object
  def deep_map(&block)
    if self.respond_to? :each
      result = []
      self.each do |e|
        result << e.deep_map(&block)
      end
      return result
    else
      return block.call(self)
    end
  end  
end

Затем примените deep_map как угодно к массиву:

> [[[3, 3, 5], [4, 3, 3]], [[3, 2, 3], [0, 3, 8]]].deep_map { |e| e > 3 ? 0 : e }
=> [[[3, 3, 0], [0, 3, 3]], [[3, 2, 3], [0, 3, 0]]] 

Или, более кратко:

class Object
  def deep_map(&block)
    respond_to?(:map) ? map{|e| e.deep_map(&block)} : block.call(self)
  end
end

Или, полиморфно:

class Object
  def deep_map(&block); block.call(self) end
end

class Array
  def deep_map(&block); map{|e| e.deep_map(&block)} end
end
2 голосов
/ 21 мая 2011

Вы можете написать метод deep_map, который вызывает map для массива, а затем для каждого элемента проверяет, является ли он подмассивом.Если это так, вызовите deep_map рекурсивно с подмассивом, иначе получите элемент.

Затем вы можете использовать этот метод deep_map, чтобы преобразовать внутренние элементы вашего многомерного массива, не затрагивая его структуру.

0 голосов
/ 21 мая 2011

Итак, если я все сделал правильно, f(x) будет проходить по многомерному массиву, пока не найдет тот, который не содержит Array или подкласса Array , в этот момент он выдаст самый внутренний массив блоку и заменит его возвращаемым значением блока.

def f x, &block
  x.map do |a|
    if a.first.class.ancestors.include? Array
      f a, &block
    else
      yield a
    end
  end
end

p(f [ [ [ 3, 3, 5 ],
        [ 4, 3, 3 ] ],
      [ [ 3, 2, 3 ],
        [ 0, 3, 8 ] ] ] do |e|
    e.reject { |x| x > 3 }
  end
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...