An array problem

G

George George

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
 
R

Robert Klemme

2009/4/2 George George said:
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 stat=
ed.
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|
=A0if B.detect(element)
=A0 =A0puts "#{element}- b"
=A0end
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?

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 =3D {}

{b =3D> "b", c =3D> "c"}.each do |ar,label|
ar.each {|el| occurrences[el] =3D label}
end

a.each do |el|
label =3D occurrences[el] and
puts "#{el} -#{label}"
end

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
 
G

George George

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
 
R

Robert Klemme

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

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

Kind regards

robert
 
G

George George

Robert said:
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.
 
R

Robert Klemme

Robert said:
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.

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
 
G

George George

Robert said:
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.
 
C

Christopher Dicely

I'd rather not make those constants (A,B,C) because they aren't as you st= ated.

You want #include? instead of #detect:

a.each do |el|
=C2=A0case
=C2=A0 =C2=A0when b.include? el
=C2=A0 =C2=A0 =C2=A0puts "#{el} -b"
=C2=A0 =C2=A0when c.include? el
=C2=A0 =C2=A0 =C2=A0puts "#{el} -c"
=C2=A0end
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=3D>'b',c=3D>'c'}.map { |arr, label|
"#{el} -#{label}" if arr.include?(el)
}
}.flatten.compact
 
R

Robert Klemme

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,

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,147
Latest member
CarenSchni
Top