Рубиновая вложенная петля - PullRequest
2 голосов
/ 30 июля 2010

У меня есть вложенный loop2 (check2) в loop1 (check1), но кажется, что вложенный loop2 (check2) выполняется только один раз.

Оба цикла содержат один и тот же массив. Этот скрипт используется для проверки дублированного идентификатора в check1.

check1=["0", "0", "0", "1", "1", "2", "3", "4", "5", "100", "4294967294", "9", "11", "6", "200", "7", "201", "811", "202", "204", "3000", "205", "3001", "3001", "3001"]
check2 =["0", "0", "0", "1", "1", "2", "3", "4", "5", "100", "4294967294", "9", "11", "6", "200", "7", "201", "811", "202", "204", "3000", "205", "3001", "3001", "3001"]

Код:

check1.each do |check1|
  counter=0
  puts "checking against:"+check1.to_s
  check2.each do |check2|
    puts "checking:"+check1.to_s+"|"+check2.to_s
    if check1 == check2
      counter += 1
    end
  end
  if counter > 1
    dupUID << check1
  end
end

Результат:

checking against:0 <- checking the 1st element in check1
checking:0|0
checking:0|0
checking:0|0
checking:0|1
checking:0|1
checking:0|2
checking:0|3
checking:0|4
checking:0|5
checking:0|100
checking:0|4294967294
checking:0|9
checking:0|11
checking:0|6
checking:0|200
checking:0|7
checking:0|201
checking:0|811
checking:0|202
checking:0|204
checking:0|3000
checking:0|205
checking:0|3001
checking:0|3001
checking:0|3001
checking against:0<- checking the 2nd element in check1
checking:0|3001   <- nested loop2(check2) is not looping again on the 2nd element of loop 1
checking against:0
checking:0|3001   <- loop2 stops at the last element for the remaining elements in check1
checking against:1
checking:1|3001
checking against:1
checking:1|3001
checking against:2
checking:2|3001
checking against:3
checking:3|3001
checking against:4
checking:4|3001
checking against:5
checking:5|3001
checking against:100
checking:100|3001
checking against:4294967294
checking:4294967294|3001
checking against:9
checking:9|3001
checking against:11
checking:11|3001
checking against:6
checking:6|3001
checking against:200
checking:200|3001
checking against:7
checking:7|3001
checking against:201
checking:201|3001
checking against:811
checking:811|3001
checking against:202
checking:202|3001
checking against:204
checking:204|3001
checking against:3000
checking:3000|3001
checking against:205
checking:205|3001
checking against:3001
checking:3001|3001
checking against:3001
checking:3001|3001
checking against:3001
checking:3001|3001

Кто-нибудь может указать на мою ошибку? Большое спасибо. Решено: Спасибо всем!

check1.each do |ch1|
  counter=0
  check2.each do |ch2|
    if ch1 == ch2
      counter += 1
    end
  end
  if counter > 1
    dupUID << ch1
  end
end

puts dupUID

Ответы [ 5 ]

2 голосов
/ 30 июля 2010

Вы скрываете массивы check1 и check2, поскольку переменные блока do имеют то же имя, что и они.

После внутреннего блока do, check2 относится к последнемуэлемент массива, а не сам массив.

Чтобы исправить это, переименуйте переменные блока в что-то вроде ch1 и ch2.

Так что это объясняет, почему вложенный цикл не 'не работает, как вы ожидаете.На самом деле, сам ваш алгоритм тоже несовершенен.Ответ @floatless дает лучший подход к проблеме.

2 голосов
/ 30 июля 2010

Полагаю, вы не должны писать такой код.Есть лучшее решение:

x = [0, 10, 15]
y = [0, 20, 15]
x & y # => [0, 15] 

Этот метод возвращает элементы, общие для указанных двух массивов.

(Обновлено) Существует еще один способ сделать это только водин массив:

[0, 10, 10, 15, 20].inject({}) 
{ 
    |a, c| a[c] ||= 0; a[c] = a[c].next; a 
}.delete_if { |k, v| v == 1 }.keys
1 голос
/ 30 июля 2010

Короче, но не более понятно:

check.inject(Hash.new(0)) { |a, x| a[x] += 1; a }.reject { |k, v| v <= 1 }.keys
0 голосов
/ 30 июля 2010

Если бы у вас были предупреждения ($VERBOSE = true), он бы уведомил вас о допущенной вами ошибке.

IRB для ruby ​​1.9.1 не позволяет вам включить $ VERBOSE в командной строке , но 1.9.2 будет.

Обновление : Этот вопрос привел меня к файлу это исправление ошибки / функции для рубина.Спасибо!

0 голосов
/ 30 июля 2010

Предполагается, что у вас есть один массив check, и вы хотите найти в нем все повторяющиеся элементы. Использование Ruby 1.9.

check.group_by {|v| v}.map { |k, v| v.size > 1 ? k : nil }.compact

Пояснение:

  • group_by возвращает хэш с ключом, который является числом, а значение - массивом каждого вхождения.
  • map возвращает либо nil, если значение встречается только один раз, либо значение, если оно встречается более одного раза.
  • compact очищает все значения nil.

Вот пошаговые результаты:

# after group_by
{"204"=>["204"], "6"=>["6"], "11"=>["11"], "205"=>["205"], "7"=>["7"], "811"=>["811"], "9"=>["9"], "4294967294"=>["4294967294"], "0"=>["0", "0", "0"], "100"=>["100"], "1"=>["1", "1"], "200"=>["200"], "2"=>["2"], "201"=>["201"], "3"=>["3"], "3000"=>["3000"], "202"=>["202"], "4"=>["4"], "3001"=>["3001", "3001", "3001"], "5"=>["5"]}>

# after map
[nil, nil, nil, nil, nil, nil, nil, nil, "0", nil, "1", nil, nil, nil, nil, nil, nil, nil, "3001", nil]

# after compact
["0", "1", "3001"]
...