рубиновый вопрос - PullRequest
       28

рубиновый вопрос

0 голосов
/ 15 января 2011

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

first_var.sort.each do |first_id, first_value|
  second_var.sort.each do |second_id, second_value_value|
    difference = first_value - second_value
    if difference >= 0
      second_var.delete(second_id)
    else
      second_var[second_id] += first_value
      if second_var[second_id] == 0
        second_var.delete(second_id)
      end
      first_var.delete(first_id)
    end
  end
end

Идея этого кода заключается в том, что я хочу использовать его для расчета того, сколько денег определенный пользователь собирается дать другому пользователю. Обе переменные содержат хэши. First_var содержит пользователей, которые будут получать деньги, а second_var содержит пользователей, которые собираются платить. Цикл должен «заполнить» пользователя, который должен получать деньги, и когда пользователь заполняется, или у пользователя нет денег, просто вывести его из цикла и продолжить заполнять остальных пользователей.

Как мне это сделать, потому что это не работает?

Ответы [ 3 ]

3 голосов
/ 15 января 2011

Хорошо. Похоже, у вас есть два хэша, отсюда и разделение «id, value».

Если вы просматриваете массивы и хотите использовать индекс массива, вам следует использовать Array.each_index.

Если вы перебираете массив объектов, а 'id' и 'value' являются атрибутами, вам нужно только вызвать некоторую произвольную переменную блока, а не две.

Предположим, что это два хэша, H1 и H2, одинаковой длины, с общими ключами. Вы хотите сделать следующее: если значение H1 [ключ]>, чем H2 [ключ]: значение, удалить ключ из H2, иначе суммировать H1: значение в H2: значение и поместить результат в H2 [ключ].

H1.each_key do |k|
  if H1[k] > H2[k] then
     H2.delete(k)
  else 
     H2[k] = H2[k]+H1[k]
  end
end

Предположим, что вы просматриваете два массива и хотите отсортировать их по значению, а затем, если значение в A1 [x] больше значения в A2 [x], удалите A2 [x]. Иначе, сумма A1 [x] с A2 [x].

   b = a2.sort
   a1.sort.each_index do |k|
      if a1[k] > b[k]
        b[k] = nil
      else
        b[k] = a1[k] + b[k]
      end
    end
    a2 = b.compact

На основании новой информации: у вас есть хеш для получателей и хеш для плательщиков. Давайте назовем их ees и ers просто для удобства. Сложность в том, что при изменении хэша ers вы можете запутать цикл. Один из способов сделать это - плохо - заключается в следующем.

e_keys = ees.keys
r_keys = ers.keys
e = 0
r = 0
until e == e_keys.length or r == r_keys.length
    ees[e_keys[e]] = ees[e_keys[e]] + ers[r_keys[r]]
    x = max_value - ees[e_keys[e]]
    ers[r_keys[r]] = x >= 0 ? 0 : x.abs 
    ees[e_keys[e]] = [ees[e_keys[e]], max_value].min
    if ers[r_keys[r]] == 0 then r+= 1 end
    if ees[e_keys[e]] == max_value then e+=1 end
end

Причина, по которой я говорю, что это не очень хорошее решение, заключается в том, что я думаю, что есть более «рубиновый» способ сделать это, но я не уверен, что это такое. Это, однако, позволяет избежать проблем, которые могут возникнуть при изменении хэша, который вы перебираете.

1 голос
/ 15 января 2011

Вы имеете в виду?

some_value = 5
arrarr = [[],[1,2,5],[5,3],[2,5,7],[5,6,2,5]]
arrarr.each do |a|
  a.delete(some_value)
end

arrarr теперь имеет значение [[], [1, 2], [3], [2, 7], [6, 2]]


IЯ думаю, что вы можете изменить переменную внутри такого цикла, но я настоятельно рекомендую против этого.Я предполагаю, что это неопределенное поведение.вот что случилось, когда я попробовал этоend

Если бы вы могли, я бы попробовал использовать каждый / map / filter / select.ect.в противном случае создайте новый массив и переберите список как обычно.Или переберите числа от x до y

1.upto (5) .each do | n |do_stuff_with (arr [n]) end

0 голосов
/ 15 января 2011

Предполагается:

some_var = [1,2,3,4]

delete_if звучит как приемлемый кандидат для этого:

some_var.delete_if { |a| a == 1 }
p some_var
=> [2,3,4]
...