Forum: Ruby An array problem

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Cd4de09b6a6cdbbf291b5963d6f02efd?d=identicon&s=25 George George (george_g)
on 2009-04-02 17:48
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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-04-02 18:24
(Received via mailing list)
2009/4/2 George George <george.githinji@gmail.com>:

> 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
Cd4de09b6a6cdbbf291b5963d6f02efd?d=identicon&s=25 George George (george_g)
on 2009-04-03 07:09
>
> 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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-04-03 08:30
(Received via mailing list)
On 03.04.2009 07:09, George George 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
Cd4de09b6a6cdbbf291b5963d6f02efd?d=identicon&s=25 George George (george_g)
on 2009-04-03 10:17
Robert Klemme 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.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-04-03 10:40
(Received via mailing list)
On 03.04.2009 10:17, George George 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
Cd4de09b6a6cdbbf291b5963d6f02efd?d=identicon&s=25 George George (george_g)
on 2009-04-03 10:55
Robert Klemme 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.
D7463bd611f227cfb2ef4da4a978a203?d=identicon&s=25 Christopher Dicely (Guest)
on 2009-04-03 17:05
(Received via mailing list)
On Thu, Apr 2, 2009 at 9:23 AM, Robert Klemme
<shortcutter@googlemail.com> 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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-04-03 18:21
(Received via mailing list)
On 03.04.2009 17:03, Christopher Dicely 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
This topic is locked and can not be replied to.