Повторный набор, покрытый перекрестным произведением диапазонов в ruby - PullRequest
0 голосов
/ 19 февраля 2011

Я подумал, что этот ответ уже задавался, поэтому я искал, но ничего не смог найти. Конечно, есть множество вопросов по Ruby Array, так что они могут быть там, просто похоронены.

В любом случае я пытаюсь уменьшить перекрестное произведение диапазонов, возвращая сумму всех элементов перекрестного произведения, которые удовлетворяют некоторому набору условий. Для построения тривиального примера, если у меня есть такой массив:

[0..1,0..1,0..1]

Я бы хотел перебрать этот набор:

[
  [0,0,0],
  [0,0,1],
  [0,1,0],
  [0,1,1],
  [1,0,0],
  [1,0,1],
  [1,1,0],
  [1,1,1]
]

и вернуть сумму на основе условия «return 1 if i[0] == 1 and i[2] == 0» (что даст 2). В моем надуманном примере я мог бы сделать это так:

br = 0..1

br.reduce(0){|sumx, x|
  sumx + br.reduce(0){|sumy, y|
    sumy + br.reduce(0){|sumz, z|
      sumz + (x == 1 and z == 0 ? 1 : 0)
    }
  }
}

, но в реальном приложении набор диапазонов может быть намного больше, и вложение сокращается таким образом, что будет довольно уродливо. Есть ли лучший способ?

1 Ответ

3 голосов
/ 19 февраля 2011

Есть две ортогональные задачи, старайтесь не смешивать их, чтобы код оставался модульным.

  1. Как построить декартово произведение из N массивов.

  2. Как отфильтровать произведение и сосчитать.

Используйте Array # product , чтобы получить декартово произведение:

xs = [0..1, 0..1, 0..1].map(&:to_a)
xss = xs[0].product(*xs[1..-1]) # or xs.first.product(*xs.drop(1))
#=> [[0, 0, 0], [0, 0, 1], [0, 1, 0], ..., [1, 1, 0], [1, 1, 1]]

А теперь сделайте фильтр и couting:

xss.count { |x, y, z| x == 1 && z == 0 }
#=> 2

Это немного уродливееэто должно произойти, потому что нам нужен метод класса Array::product вместо метода Array#product.Нет проблем, давайте добавим его в наш модуль расширений и напоследок напишем:

Array.product(0..1, 0..1, 0..1).count { |x, y, z| x == 1 && z == 0 }
#=> 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...