An array problem


#1

Hi
i have a 3 arrays(A,B,C) which are results of some analysis.
Array A has all members such that array B and C are actually subsets of
A. The order of elements in array A is important.

What i want is to list all members of A such that if an element in A is
a found in B or C produce a report such as

element1 -b
element2 -b
element3 -c
element4 -b

where the order of elements in the report is as was in array A.

my rather silly implentation was
A.each do |element|
if B.detect(element)
puts “#{element}- b”
end
end

however i don’t think this is the right way to do it since it does not
give me the designed result. Can someone help me spot the bug?

Thank you
George


#2

2009/4/2 George G. removed_email_address@domain.invalid:

i have a 3 arrays(A,B,C) which are results of some analysis.

I’d rather not make those constants (A,B,C) because they aren’t as you
stated.

however i don’t think this is the right way to do it since it does not
give me the designed result. Can someone help me spot the bug?

You want #include? instead of #detect:

a.each do |el|
case
when b.include? el
puts “#{el} -b”
when c.include? el
puts “#{el} -c”
end
end

Another hint: if A is really large (say 10_000 elements or more) it
might be more efficient to convert B and C into Sets which have faster
inclusion test.

Or do it this way:

occurrences = {}

{b => “b”, c => “c”}.each do |ar,label|
ar.each {|el| occurrences[el] = label}
end

a.each do |el|
label = occurrences[el] and
puts “#{el} -#{label}”
end

Kind regards

robert


#3

You want #include? instead of #detect:

a.each do |el|
case
when b.include? el
puts “#{el} -b”
when c.include? el
puts “#{el} -c”
end
end

Thanks a lot Robert, However this solution does not seem to preserve the
order in of array a.
for example if array a contained
a = [“x”,“y”,“z”,“f”]
b = [“y”,“z”]
c = [“x”,“f”]

the result should be

x-c
y-b
z-b
f-c

Thanks
GG


#4

On 03.04.2009 07:09, George G. wrote:

y-b
z-b
f-c

I don’t see how the order in a could not be preserved. Please check
again oder provide full code.

Kind regards

robert


#5

Robert K. wrote:

I don’t see how the order in a could not be preserved. Please check
again oder provide full code.

Here is the code
#original list
@list_of_names

#mcl.total_clusters provides a count for the number of clusters #or
arrays available(a.k.a, my b and c in the previous #descriptions)

#an iterator that counts the number of arrays available(subsets #of
@cluster_members
mcl.total_clusters.times do |i|
cluster_members = mcl.cluster_members_for(i)

@list_of_names.each do |el|
case
when cluster_members.include?(el)
puts “#{el} - #{i}”
end
end
end

Given: @list_of_names =
[10Atig18,10Atig8,10Atig7,10Atig3,10Btig15,10Btig11,10Btig1],

and cluster b=[10Atig8,10Atig3,10Btig1] while the rest of the members
belonged to cluster c

produce a report such that
10Atig18 -c
10Atig8 -b
10Atig7 -c
10Atig3 -b
10Btig15 -c
10Btig11 -c
10Btig1 -b

The implementation above produces this,
10Atig8 -b
10Atig3 -b
10Btig1 -b
10Atig18 -c
10Atig7 -c
10Btig15 -c
10Btig11 -c

which is not what is required.


#6

Robert K. wrote:

George, you claimed that the code I presented does not maintain order.
Now you present totally different code as “proof”. The error is in
your code. Btw, you also did not state that the number of cluster
arrays (b and c) is not fixed which is of course why you could not use
the bit you claimed would not maintain order. Please go back to my
original posting - you’ll find building blocks for a solution there.
I’ll leave the rest to you.

True, the error is in my code. Thank you for providing the clues.


#7

On Thu, Apr 2, 2009 at 9:23 AM, Robert K.
removed_email_address@domain.invalid wrote:

a found in B or C produce a report such as
my rather silly implentation was

a.each do |el|
 case
  when b.include? el
   puts “#{el} -b”
  when c.include? el
   puts “#{el} -c”
 end
end

Neither ruby 1.8.6 (in IRB) or Jruby 1.2.0 (in jirb_swing) likes this
without parenthesizing the argument to include? in the when clauses,
but a bigger problem is that if both b and c include a value it will
only print that b did, since when clauses are exclusive.

If its not essential to preprocess the arrays as in your second
approach, the following works:

puts a.map { |el|
{b=>‘b’,c=>‘c’}.map { |arr, label|
“#{el} -#{label}” if arr.include?(el)
}
}.flatten.compact


#8

On 03.04.2009 10:17, George G. wrote:

arrays available(a.k.a, my b and c in the previous #descriptions)
end
produce a report such that
10Atig3 -b
10Btig1 -b
10Atig18 -c
10Atig7 -c
10Btig15 -c
10Btig11 -c

which is not what is required.

George, you claimed that the code I presented does not maintain order.
Now you present totally different code as “proof”. The error is in
your code. Btw, you also did not state that the number of cluster
arrays (b and c) is not fixed which is of course why you could not use
the bit you claimed would not maintain order. Please go back to my
original posting - you’ll find building blocks for a solution there.
I’ll leave the rest to you.

Regards

robert


#9

On 03.04.2009 17:03, Christopher D. wrote:

What i want is to list all members of A such that if an element in A is

without parenthesizing the argument to include? in the when clauses,
Right, I should have made the check. Thank you for pointing this out.

but a bigger problem is that if both b and c include a value it will
only print that b did, since when clauses are exclusive.

This is not a problem of my code but in the problem specification.
There was no statement about whether elements can occur in multiple of
the subsets and if so, whether there is any priority defined. Since
maintaining original order was stated important reporting an element
more than once was not an option for me.

If its not essential to preprocess the arrays as in your second
approach, the following works:

puts a.map { |el|
{b=>‘b’,c=>‘c’}.map { |arr, label|
“#{el} -#{label}” if arr.include?(el)
}
}.flatten.compact

I always find it inelegant to produce nested Arrays which can contain
nils and then getting rid of them using flatten and compact. That’s
mostly an issue of personal taste but in cases where there can be many
nils compared to non nils this is also about efficiency.

Apropos: in your code you’ll create the same Hashes all the time. You
could at least factor that out.

Kind regards

robert