Create variables depending on counter

Hi community,

First of all sorry for my english and I hope you get what I want to say.
As an example let us say I have an Array like this:

Car
Dog
Car
Car
Dog

What i want to do is I want to collect all Cars in a new Array and all
Dogs in a new Array, too.
So I need two new Arrays to do this. With Array.uniq.length I get the
number of my new Arrays I need.
Is there a way to implement this that the programme counts the uniq
elements in the array and creates variables depending on the counter.

So difficult to explain. I hope anyone can help me.

Thanks

···

--
Posted via http://www.ruby-forum.com/.

I do not understand completely.
What should the two new arrays look like?

['Dog', 'Dog'], ['Car', 'Car', 'Car'] ???

Doesn't make too much sense to me...

Regards,
Marcus

···

Am 09.07.2013 17:13, schrieb stefan heinrich:

Hi community,

First of all sorry for my english and I hope you get what I want to say.
As an example let us say I have an Array like this:

Car
Dog
Car
Dog

What i want to do is I want to collect all Cars in a new Array and all
Dogs in a new Array, too.
So I need two new Arrays to do this. With Array.uniq.length I get the
number of my new Arrays I need.
Is there a way to implement this that the programme counts the uniq
elements in the array and creates variables depending on the counter.

So difficult to explain. I hope anyone can help me.

--
<https://github.com/stomar/&gt;

Hi,

as I already said, it's not completely clear to me what you want to do.
Anyway, I believe what you need is a hash :slight_smile:

Some use cases I could imagine:

Get a list of indices for all uniq elements:

array = ['Car', 'Dog', 'Dog', 'Car', 'Dog']
indices = Hash.new {|h,k| h[k] = }
array.each_with_index {|element, index| indices[element] << index }
indices
   # => {"Car"=>[0, 3], "Dog"=>[1, 2, 4]}
indices['Car']
   # => [0, 3]
indices['Dog']
   # => [1, 2, 4]

Count the number of occurences:

occurences = Hash.new(0)
array.each {|element| occurences[element] += 1 }
occurences
   # => {"Car"=>2, "Dog"=>3}

Regards,
Marcus

···

Am 09.07.2013 17:13, schrieb stefan heinrich:

As an example let us say I have an Array like this:

Car
Dog
Car
Dog

What i want to do is I want to collect all Cars in a new Array and all
Dogs in a new Array, too.
So I need two new Arrays to do this. With Array.uniq.length I get the
number of my new Arrays I need.
Is there a way to implement this that the programme counts the uniq
elements in the array and creates variables depending on the counter.

So difficult to explain. I hope anyone can help me.

--
<https://github.com/stomar/&gt;

Yes as you mentioned it should look like

['Dog', 'Dog'] and
['Car, Car, Car].

If it doesn't make sense for you i have to explain more.

I have a gui with a tablewidget.
Dog and Car are only row Headlines.

               Values
Dog | 12
Car | 14
Car | 67
Dog | 98
Dog | 32

I search for the Headlines and get the value from the current row. My
programme has to be intelligent and he should knows how many different
headlines I have. Depending on how many Variables I have my programme
should create new Array with only the values with the same headline.
Like this:

Arraydog = 12, 98, 32
Arraycar = 14, 67

Now I can combinate each value from the array with the values from the
other Arrays. The main thing is one value shouldn't combine with a value
in the same class. I have this code:

a= arraydog, arraycar
combine = a.first.product(*a[1..-1]).map(&:join)

It works fine but only if I have two different Headlines. With more or
less headlines it doesn't works...

···

--
Posted via http://www.ruby-forum.com/.

Hi marcus,

can u say how I have to use the Hash with the headers. I have tried
everything but it doesn't work.

Thanks

···

--
Posted via http://www.ruby-forum.com/.

Hi Robert and Marcus,

thanks for your help. Both methods are working very fine :D.
But now I have the Problem that I couldn't combine the values.

The Result of my script looks like:

=> {"I OFF"=>["34"], "E OFF"=>["92", "94"], "E ON"=>["7f"],
    "I ON"=>["d9", "cf"]}

I get always a nil when I want combine each value from one Array with
the other values from the other Arrays. I use

data.first.product(*data[1..-1]).map(&:join)

Can u say what the problem is now?

And if its possible can you explain how I can only combine I with E
values.
It doesnt make sense if I combine "I ON" with "I OFF" or "E ON" with "E
OFF".

Thank u so much. I have been working for a few days but i dont find
anything.

···

--
Posted via http://www.ruby-forum.com/.

Well done :D...

I select the E with I and I with E like the following code. The
variables possible..possible3 are arrays.

   possible << array.select {|k,| /^I ON/ =~ k} <<
   array.select {|k,| /^E OFF/ =~ k}

   possible1 << array.select {|k,| /^I ON/ =~ k} <<
   array.select {|k,| /^E ON/ =~ k}

   possible2 << array.select {|k,| /^I OFF/ =~ k} <<
   array.select {|k,| /^E OFF/ =~ k}

   possible3 << array.select {|k,| /^I OFF/ =~ k} <<
   array.select {|k,| /^E ON/ =~ k}

One example of the possible combinations looks like:

   [[["I OFF", ["10", "e6"]]],
   [["E ON", ["1f", "e9"]]]]

The last step before i have finished is :smiley: that I would combine the
values.
I would like to have

10 1f
10 e9
e6 1f
e6 e9
1f 10
e9 10
1f e6
e9 e6

Is it possible to do it?

···

--
Posted via http://www.ruby-forum.com/.

Ok i got it. Thank you so much.

One more question.
Is it better if I work here with symbols instead of strings like I ON
etc...

Best regards

···

--
Posted via http://www.ruby-forum.com/.

I think you would be better served by using hashes instead of arrays for something like this.

Yes as you mentioned it should look like

['Dog', 'Dog'] and
['Car, Car, Car].

If it doesn't make sense for you i have to explain more.

I have a gui with a tablewidget.
Dog and Car are only row Headlines.

                Values
Dog | 12
Car | 14
Car | 67
Dog | 98
Dog | 32

[...]

Depending on how many Variables I have my programme
should create new Array with only the values with the same headline.
Like this:

Arraydog = 12, 98, 32
Arraycar = 14, 67

You should use a hash with the headers as keys.

My examples can very easily be adapted to do exactly what you need.

Regards,
Marcus

···

Am 09.07.2013 20:55, schrieb stefan heinrich:

--
<https://github.com/stomar/&gt;

Hi marcus,

can u say how I have to use the Hash with the headers. I have tried
everything but it doesn't work.

Thanks

--
Posted via http://www.ruby-forum.com/\.

Hi stefan,

One way you can build up an structure which mimics

Arraydog = 12, 98, 32
Arraycar = 14, 67

might be:

ratdog:~ mike$ pry
[1] pry(main)> records = Hash.new { |h, k| h[k] = }
=> {}
[2] pry(main)> records[:dog] << 12
=> [12]
[3] pry(main)> records[:dog] << 98
=> [12, 98]
[4] pry(main)> records[:car] << 14
=> [14]
[5] pry(main)> records[:car] << 67
=> [14, 67]
[6] pry(main)> records[:dog] << 32
=> [12, 98, 32]
[7] pry(main)> records
=> {:dog=>[12, 98, 32], :car=>[14, 67]}

Hope this helps,

Mike

···

On 2013-07-09, at 6:03 PM, stefan heinrich <lists@ruby-forum.com> wrote:

--

Mike Stok <mike@stok.ca>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.

can u say how I have to use the Hash with the headers. I have tried
everything but it doesn't work.

That's not a very useful information...

You can take my first example:

array = ['Car', 'Dog', 'Dog', 'Car', 'Dog']
indices = Hash.new {|h,k| h[k] = }
array.each_with_index {|element, index| indices[element] << index }
indices
   # => {"Car"=>[0, 3], "Dog"=>[1, 2, 4]}
indices['Car']
   # => [0, 3]
indices['Dog']
   # => [1, 2, 4]

assuming your data is given as a 2-dimensional array:

data = [
   ['Dog', 12],
   ['Car', 14],
   ['Car', 67],
   ['Dog', 98],
   ['Dog', 32]
]

then this would work (first, I create a hash with as the
default value, that's the trickiest part of the whole thing):

values = Hash.new {|h,k| h[k] = }
data.each {|header, value| values[header] << value }
p values['Dog'] # [12, 98, 32]
p values['Car'] # [14, 67]

Depending on how your data is given, you need to modify
the second line.

I suggest you also look into the docs for the Hash class and
make heavy use of irb.

Regards,
Marcus

···

Am 10.07.2013 00:03, schrieb stefan heinrich:
Am 09.07.2013 17:47, schrieb sto.mar@web.de:

--
<https://github.com/stomar/&gt;

Hi Robert and Marcus,

thanks for your help. Both methods are working very fine :D.
But now I have the Problem that I couldn't combine the values.

The Result of my script looks like:

=> {"I OFF"=>["34"], "E OFF"=>["92", "94"], "E ON"=>["7f"],
    "I ON"=>["d9", "cf"]}

Why are the elements in the arrays not numbers? It looks like you rather
want to work with numbers (Fixnum) here.

I get always a nil when I want combine each value from one Array with

the other values from the other Arrays. I use

data.first.product(*data[1..-1]).map(&:join)

Can u say what the problem is now?

Can you show us what's in data? Please make sure to present complete
examples, otherwise it's difficult to come up with answers - and to follow
the discussion as well.

And if its possible can you explain how I can only combine I with E
values.
It doesnt make sense if I combine "I ON" with "I OFF" or "E ON" with "E
OFF".

Well, just select e.g.

irb(main):001:0> h = {"I OFF"=>["34"], "E OFF"=>["92", "94"], "E
ON"=>["7f"], "I ON"=>["d9", "cf"]}
=> {"I OFF"=>["34"], "E OFF"=>["92", "94"], "E ON"=>["7f"], "I ON"=>["d9",
"cf"]}
irb(main):002:0> h.select {|k,| /^I/ =~ k}
=> {"I OFF"=>["34"], "I ON"=>["d9", "cf"]}
irb(main):003:0> h.select {|k,| /^E/ =~ k}
=> {"E OFF"=>["92", "94"], "E ON"=>["7f"]}

Kind regards

robert

···

On Wed, Jul 10, 2013 at 4:21 PM, stefan heinrich <lists@ruby-forum.com>wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

It depends. Where do you get the data from? Is it a fixed set of values?
etc.

Kind regards

robert

···

On Fri, Jul 12, 2013 at 12:27 AM, stefan heinrich <lists@ruby-forum.com>wrote:

One more question.
Is it better if I work here with symbols instead of strings like I ON
etc...

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

can u say how I have to use the Hash with the headers. I have tried

everything but it doesn't work.

That's not a very useful information...

You can take my first example:

array = ['Car', 'Dog', 'Dog', 'Car', 'Dog']

indices = Hash.new {|h,k| h[k] = }
array.each_with_index {|element, index| indices[element] << index }
indices
   # => {"Car"=>[0, 3], "Dog"=>[1, 2, 4]}
indices['Car']
   # => [0, 3]
indices['Dog']
   # => [1, 2, 4]

assuming your data is given as a 2-dimensional array:

data = [
  ['Dog', 12],
  ['Car', 14],
  ['Car', 67],
  ['Dog', 98],
  ['Dog', 32]
]

then this would work (first, I create a hash with as the
default value, that's the trickiest part of the whole thing):

values = Hash.new {|h,k| h[k] = }
data.each {|header, value| values[header] << value }

You can also use Enumerable#group_by:

irb(main):008:0> data.group_by {|s,i| s}
=> {"Dog"=>[["Dog", 12], ["Dog", 98], ["Dog", 32]], "Car"=>[["Car", 14],
["Car", 67]]}
irb(main):009:0> data.group_by {|s,i| s}.each {|k,v| v.map! {|s,i| i}}
=> {"Dog"=>[12, 98, 32], "Car"=>[14, 67]}

Depending on how your data is given, you need to modify
the second line.

I was going to ask in what structure the data is available. That bit of
information seems to be missing from the discussion.

I suggest you also look into the docs for the Hash class and

make heavy use of irb.

That's excellent advice.

Kind regards

robert

···

On Wed, Jul 10, 2013 at 7:14 AM, <sto.mar@web.de> wrote:

Am 10.07.2013 00:03, schrieb stefan heinrich:
Am 09.07.2013 17:47, schrieb sto.mar@web.de:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Hi,

Why are the elements in the arrays not numbers? It looks like you
rather
want to work with numbers (Fixnum) here.

It's not only numbers. In some cases there are strings.

Can you show us what's in data? Please make sure to present complete
examples, otherwise it's difficult to come up with answers - and to
follow
the discussion as well.

ok sorry...
my code to read out the tablewidget and create the array.

    array = Array.new

    for i in 0..rowCount - 1
      tmp = Array.new
      tmp << @tableWidget.item(i, 1).text.to_a
      tmp << @tableWidget.item(i, 0).text.to_a
      tmp = tmp[0] + tmp[1]

      array << tmp
    end

    array.group_by {|s,i| s}
    array= array.group_by {|s,i| s}.each {|k,v| v.map! {|s,i| i}}

The 2d array looks like this after grouping

{"I OFF"=>["a8", "1e"], "E OFF"=>["98", "a0"], "Emphasized ON"=>["db"],
"I ON"=>["99"]}

It seems like after using grouping by it is not an array anymore. I use
array[0] and get a nil. How can I take only the values. I would like to
combine all combinations only I with E and E with I. It is not working.

irb(main):001:0> h = {"I OFF"=>["34"], "E OFF"=>["92", "94"], "E
ON"=>["7f"], "I ON"=>["d9", "cf"]}
=> {"I OFF"=>["34"], "E OFF"=>["92", "94"], "E ON"=>["7f"], "I
ON"=>["d9",
"cf"]}
irb(main):002:0> h.select {|k,| /^I/ =~ k}
=> {"I OFF"=>["34"], "I ON"=>["d9", "cf"]}
irb(main):003:0> h.select {|k,| /^E/ =~ k}
=> {"E OFF"=>["92", "94"], "E ON"=>["7f"]}

I have to try it now :D. Thanks

···

--
Posted via http://www.ruby-forum.com/\.

Hi,

It depends. Where do you get the data from? Is it a fixed set of
values?
etc.

ok, give me a try to explain. Lets take a look in the Hash

{"I OFF"=>["a8", "1e"], "E OFF"=>["98", "a0"], "E ON"=>["db"],
"I ON"=>["99"]}

The values "a8", "1e", "98" etc. are random generated values. There are
not fixed but they have an interval. Depending on the value if the LSB =
1 it is an ON and LSB = 0 it is a OFF. So normally we can say without
looking to the syntax

  def value_?even(value)
    return :E_ON if value & 0x01
    return :E_OFF
  end

But for a ruby newbie it is very difficult and confusing to understand
symbols in ruby. I have read so much articles and looked for example to
get it. But I think I need more time to understand symbols.

Now what do you suggest me, is it possible to implement this like I
explained?

···

--
Posted via http://www.ruby-forum.com/\.

Hi,

> Why are the elements in the arrays not numbers? It looks like you
> rather
> want to work with numbers (Fixnum) here.

It's not only numbers. In some cases there are strings.

> Can you show us what's in data? Please make sure to present complete
> examples, otherwise it's difficult to come up with answers - and to
> follow
> the discussion as well.

ok sorry...
my code to read out the tablewidget and create the array.

    array = Array.new

    for i in 0..rowCount - 1
      tmp = Array.new
      tmp << @tableWidget.item(i, 1).text.to_a
      tmp << @tableWidget.item(i, 0).text.to_a
      tmp = tmp[0] + tmp[1]

      array << tmp
    end

You can make your life a tad easier by not creating all those one element
arrays with the #to_a call:

array = row_count.times.map do |i|
  [1, 0].map! {|idx| @table_widget.item(i, idx).text}
end

Note the different spelling: in Ruby we use CamelCase only for classes and
modules and snake_case for the rest.

    array.group_by {|s,i| s}

This line does nothing. More precisely: it creates a Hash and then
immediately forgets it.

    array= array.group_by {|s,i| s}.each {|k,v| v.map! {|s,i| i}}

The 2d array looks like this after grouping

{"I OFF"=>["a8", "1e"], "E OFF"=>["98", "a0"], "Emphasized ON"=>["db"],
"I ON"=>["99"]}

It seems like after using grouping by it is not an array anymore. I use
array[0] and get a nil. How can I take only the values. I would like to
combine all combinations only I with E and E with I. It is not working.

Reading the documentation sometimes really helps. :slight_smile:

Cheers

robert

···

On Thu, Jul 11, 2013 at 9:34 AM, stefan heinrich <lists@ruby-forum.com>wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

my code to read out the tablewidget and create the array.

     array = Array.new

     for i in 0..rowCount - 1
       tmp = Array.new
       tmp << @tableWidget.item(i, 1).text.to_a
       tmp << @tableWidget.item(i, 0).text.to_a
       tmp = tmp[0] + tmp[1]

       array << tmp
     end

     array.group_by {|s,i| s}
     array= array.group_by {|s,i| s}.each {|k,v| v.map! {|s,i| i}}

The 2d array looks like this after grouping

{"I OFF"=>["a8", "1e"], "E OFF"=>["98", "a0"], "Emphasized ON"=>["db"],
"I ON"=>["99"]}

It seems like after using grouping by it is not an array anymore.

Yes indeed, as mentioned several times in the previous posts, we are
talking about a **Hash** of key-value pairs (where the values in this
case are arrays). And I already demonstrated in my examples how you
can access the stored arrays separately.

A reminder:

   data = {"I OFF"=>["a8", "1e"], "E OFF"=>["98", "a0"], "Emphasized ON"=>["db"], "I ON"=>["99"]}
   p data['I OFF'] # => ["a8", "1e"]

Also, I would like to repeat myself:

   > I suggest you also look into the docs for the Hash class and
   > make heavy use of irb.

And: Try to figure out what happens in the code examples that
people provide here.

Regards,
Marcus

···

Am 11.07.2013 09:34, schrieb stefan heinrich:

--
<https://github.com/stomar/&gt;

> It depends. Where do you get the data from? Is it a fixed set of
> values? etc.

ok, give me a try to explain. Lets take a look in the Hash

I would prefer to look at the input data and see the larger picture.

{"I OFF"=>["a8", "1e"], "E OFF"=>["98", "a0"], "E ON"=>["db"],
"I ON"=>["99"]}

The values "a8", "1e", "98" etc. are random generated values. There are
not fixed but they have an interval. Depending on the value if the LSB =
1 it is an ON and LSB = 0 it is a OFF. So normally we can say without
looking to the syntax

  def value_?even(value)
    return :E_ON if value & 0x01
    return :E_OFF
  end

Actually, to me it seems there are two values encoded in those Strings you
have above: one is either "I" or "E" and another one is "ON" or "OFF". For
me that means a much more appropriate way to store it would be an instance
with two attributes. You can easily have that with a Struct:

NameOfYourData = Struct.new :whatever_that_means, :enabled do
  def self.from_string(s)
    raise ArgumentError, "Invalid input: #{s}" unless
/\A(\w+)\s+(O(?:N|OFF))\z/ =~ s
    new($1, $2 == "ON")
  end
end

irb(main):007:0> x = NameOfYourData.from_string "E ON"
=> #<struct NameOfYourData whatever_that_means="E", enabled=true>
irb(main):008:0> x.enabled
=> true
irb(main):009:0> x.whatever_that_means
=> "E"

Of course you would pick more meaningful names.

But for a ruby newbie it is very difficult and confusing to understand

symbols in ruby. I have read so much articles and looked for example to
get it. But I think I need more time to understand symbols.

It's fairly easy when to use Symbols: you do that if the set of values is
restricted. In other programming languages you would often use an enum for
that (i.e. a type with a fixed set of values).

Now what do you suggest me, is it possible to implement this like I
explained?

As I said: without seeing the big picture and understanding what all this
is about and what those different strings represent it's not possible to
come up with good advice. We would need to know

- what the input data looks like
- what it means
- what you want to do with it
- what the whole purpose of the exercise is

Cheers

robert

···

On Fri, Jul 12, 2013 at 9:23 AM, stefan heinrich <lists@ruby-forum.com>wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/