Reputation: 23
I have a nested loop2(check2) in loop1(check1) but it seems that nested loop2(check2) only runs once.
Both loops contain the same array. This script is used to check for a duplicate id in 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"]
Code:
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
The result:
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
Can anyone point out my mistake? Thanks a lot. Solved: Thanks to all!
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
Upvotes: 2
Views: 8814
Reputation: 81450
If you had warnings on ($VERBOSE = true
), it'd notify you about the mistake you had.
IRB for ruby 1.9.1 doesn't allow you to turn on $VERBOSE at the command line, but 1.9.2 will.
Update: This question lead me to file this bug/feature improvement for ruby. Thanks!
Upvotes: 0
Reputation: 141859
Assuming you have a single array check
and you want to find all duplicate elements within it. Using Ruby 1.9.
check.group_by {|v| v}.map { |k, v| v.size > 1 ? k : nil }.compact
Explanation:
group_by
returns a Hash with key being the number and value being an array of each occurrence.map
returns either nil if the value occurs only once, or the value if it occurs more than once.compact
cleans up all nil
values.Here are the step by step results:
# 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"]
Upvotes: 0
Reputation: 13438
I guess you shouldn't write such code. There is a better solution:
x = [0, 10, 15]
y = [0, 20, 15]
x & y # => [0, 15]
This method returns elements common to the specified two arrays.
(Updated) There is another way to do it within only one array:
[0, 10, 10, 15, 20].inject({})
{
|a, c| a[c] ||= 0; a[c] = a[c].next; a
}.delete_if { |k, v| v == 1 }.keys
Upvotes: 2
Reputation: 198314
Shorter, but not more understandable:
check.inject(Hash.new(0)) { |a, x| a[x] += 1; a }.reject { |k, v| v <= 1 }.keys
Upvotes: 1
Reputation: 37612
You are shadowing the check1
and check2
arrays because the do
block variables have the same name as them.
After the inner do
block, check2
refers to the last element of the array, not the array itself.
To fix this, rename the block variables to something like ch1
and ch2
.
So this explains why the nested loop isn't running as you expect. Actually, your algorithm itself is also flawed. The answer of @floatless gives a better approach to the problem.
Upvotes: 2