All occurances of a character in a string

Hi - I am trying to figure out the ruby way of printing all occurances
of a character in a string..

The index method on string gives only the first occurance only.

Example input string - abbccdaab
desired output - 'a' = 0 6 7
                 'b' = 1 2 8
                 'c' = 3 4
                 'd' = 5

Any help greatly appreciated..

···

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

Hi Raghu

My 2-minute horrible-hack(tm):

input = "abbccdaab"
i = 0;
input.split('').inject({}) {|a,v| a[v] = a[v] ? (a[v] << input[i..-1].index(v)+i) : [input[i..-1].index(v)+i]; i+=1; a}

{"a"=>[0, 6, 7], "b"=>[1, 2, 8], "c"=>[3, 4], "d"=>[5]}

I am sure there has to be a *MUCH* nicer way though, because this is rather ugly...

Cheers,
Peter

···

___
http://www.rubyrailways.com
http://scrubyt.org

On Apr 26, 2008, at 2:55 PM, Raghu Go wrote:

Hi - I am trying to figure out the ruby way of printing all occurances
of a character in a string..

The index method on string gives only the first occurance only.

Example input string - abbccdaab
desired output - 'a' = 0 6 7
                'b' = 1 2 8
                'c' = 3 4
                'd' = 5

Any help greatly appreciated..
--
Posted via http://www.ruby-forum.com/\.

S2 wrote:

S2 wrote:

irb(main):006:1> ret[c] = ret[c].nil? ? d : d << ret[c]
irb(main):007:1> ret[c].flatten!

oh sorry, here are a few things that are not needed:
a = "abbccdaab"
i = 0
ret = Hash.new
a.scan(/./) {|c|
  ret[c] = ret[c].nil? ? [i] : ret[c] << i
  i = i + 1
}
p a
p ret

The block form of Hash.new gets rid of the if-statement; like this:

str = "abbccdaab"
ar = str.split("")
result = Hash.new{Array.new}

ar.each_with_index do|item,index|
  result[item] = result[item]<<index
end

result.each{|k,v| puts k + " = " + v.join(",")}

regards,

Siep

···

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

Hi --

Hi - I am trying to figure out the ruby way of printing all occurances
of a character in a string..

The index method on string gives only the first occurance only.

Example input string - abbccdaab
desired output - 'a' = 0 6 7
                'b' = 1 2 8
                'c' = 3 4
                'd' = 5

Any help greatly appreciated..

I have this really strong feeling that there's a really easy way, but
I can't think of it or find it. Meanwhile, if you're using 1.9 you
could do something like:

   str = "abcdbcdae"

   h = Hash.new {|h,k| h[k] = }
   str.each_char.map.with_index {|char, i| h[char] << i }

which would put a hash of results in h.

I just have this hunch that there was a way to accumulate offsets from
a scan or gsub operation, but I can't come up with it.

David

···

On Sat, 26 Apr 2008, Raghu Go wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

Here is one way.

arr = "abbccdaab".split(//)
arr.uniq.each do |s|
res =
(0...arr.length).each {|x| res << x if arr =~ /#{s}/}
p s, res
end

Harry

···

On Sat, Apr 26, 2008 at 9:55 PM, Raghu Go <rgowka1@gmail.com> wrote:

Hi - I am trying to figure out the ruby way of printing all occurances
of a character in a string..

The index method on string gives only the first occurance only.

Example input string - abbccdaab
desired output - 'a' = 0 6 7
                 'b' = 1 2 8
                 'c' = 3 4
                 'd' = 5

Any help greatly appreciated..
--
Posted via http://www.ruby-forum.com/\.

--
A Look into Japanese Ruby List in English

I did a quick test and like Siep's modifications..

Method1 Time elapsed: 0.236999988555908 milliseconds

Siep's modification Method2 Time elapsed: 0.123999834060669 milliseconds

def method1(a)
  i = 0
  ret = Hash.new
  a.scan(/./) {|c|
    ret[c] = ret[c].nil? ? [i] : ret[c] << i
    i = i + 1
  }
  p a
  p ret
end

def method2(str) #Siep
  ar = str.split("")
  result = Hash.new{Array.new}

  ar.each_with_index do|item,index|
    result[item] = result[item]<<index
  end
  result.each{|k,v| puts k + " = " + v.join(",")}
end

Siep Korteling wrote:

···

S2 wrote:

S2 wrote:

irb(main):006:1> ret[c] = ret[c].nil? ? d : d << ret[c]
irb(main):007:1> ret[c].flatten!

oh sorry, here are a few things that are not needed:
a = "abbccdaab"
i = 0
ret = Hash.new
a.scan(/./) {|c|
  ret[c] = ret[c].nil? ? [i] : ret[c] << i
  i = i + 1
}
p a
p ret

The block form of Hash.new gets rid of the if-statement; like this:

str = "abbccdaab"
ar = str.split("")
result = Hash.new{Array.new}

ar.each_with_index do|item,index|
  result[item] = result[item]<<index
end

result.each{|k,v| puts k + " = " + v.join(",")}

regards,

Siep

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

Hi --

Hi - I am trying to figure out the ruby way of printing all occurances
of a character in a string..

The index method on string gives only the first occurance only.

Example input string - abbccdaab
desired output - 'a' = 0 6 7
                'b' = 1 2 8
                'c' = 3 4
                'd' = 5

Any help greatly appreciated..

I have this really strong feeling that there's a really easy way, but
I can't think of it or find it. Meanwhile, if you're using 1.9 you
could do something like:

   str = "abcdbcdae"

   h = Hash.new {|h,k| h[k] = }
   str.each_char.map.with_index {|char, i| h[char] << i }

which would put a hash of results in h.

In 1.8

irb(main):001:0> require 'enumerator'
=> true
irb(main):002:0> str = "abcdbcdae"
=> "abcdbcdae"
irb(main):003:0> ind = Hash.new {|h,k| h[k]=}
=> {}
irb(main):004:0> str.to_enum(:scan,/./).each_with_index {|c,i|ind[c]<<i}
=> #<Enumerable::Enumerator:0x7ff75768>
irb(main):005:0> ind
=> {"a"=>[0, 7], "b"=>[1, 4], "c"=>[2, 5], "d"=>[3, 6], "e"=>[8]}

I just have this hunch that there was a way to accumulate offsets from
a scan or gsub operation, but I can't come up with it.

Like this?

irb(main):017:0> str = "abcdbcdae"
=> "abcdbcdae"
irb(main):018:0> ind = Hash.new {|h,k| h[k]=}
=> {}
irb(main):019:0> str.scan(/./) {|c| ind[c] << $`.length}
=> "abcdbcdae"
irb(main):020:0> ind
=> {"a"=>[0, 7], "b"=>[1, 4], "c"=>[2, 5], "d"=>[3, 6], "e"=>[8]}

Cheers

  robert

···

On 26.04.2008 16:53, David A. Black wrote:

On Sat, 26 Apr 2008, Raghu Go wrote:

> Hi - I am trying to figure out the ruby way of printing all occurances
> of a character in a string..
>
> The index method on string gives only the first occurance only.

I thought of the 'indexes' method, but that works in reverse. So I
made my own version:

class Array
  def all_indexes val
    (0..length).map{|i|self[i]==val ? i : nil}.compact
  end
  alias :all_indicies :all_indexes
end

p 'hello world'.split('').all_indicies('l')

=> [2, 3, 9]

>
> Example input string - abbccdaab
> desired output - 'a' = 0 6 7
> 'b' = 1 2 8
> 'c' = 3 4
> 'd' = 5
>
> Any help greatly appreciated..

Source = 'abbccdaab'
s=Source.split('')
s.uniq.each{|v| puts "'#{v}' = #{s.all_indexes(v)*' '}"}

=> 'a' = 0 6 7
   'b' = 1 2 8
   'c' = 3 4
   'd' = 5

-Adam

···

On Sat, Apr 26, 2008 at 9:55 PM, Raghu Go <rgowka1@gmail.com> wrote:

Hi --

···

On Sun, 27 Apr 2008, Robert Klemme wrote:

On 26.04.2008 16:53, David A. Black wrote:

Hi --

On Sat, 26 Apr 2008, Raghu Go wrote:

Hi - I am trying to figure out the ruby way of printing all occurances
of a character in a string..

The index method on string gives only the first occurance only.

Example input string - abbccdaab
desired output - 'a' = 0 6 7
                'b' = 1 2 8
                'c' = 3 4
                'd' = 5

Any help greatly appreciated..

I have this really strong feeling that there's a really easy way, but
I can't think of it or find it. Meanwhile, if you're using 1.9 you
could do something like:

   str = "abcdbcdae"

   h = Hash.new {|h,k| h[k] = }
   str.each_char.map.with_index {|char, i| h[char] << i }

which would put a hash of results in h.

In 1.8

irb(main):001:0> require 'enumerator'
=> true
irb(main):002:0> str = "abcdbcdae"
=> "abcdbcdae"
irb(main):003:0> ind = Hash.new {|h,k| h[k]=}
=> {}
irb(main):004:0> str.to_enum(:scan,/./).each_with_index {|c,i|ind[c]<<i}
=> #<Enumerable::Enumerator:0x7ff75768>
irb(main):005:0> ind
=> {"a"=>[0, 7], "b"=>[1, 4], "c"=>[2, 5], "d"=>[3, 6], "e"=>[8]}

I just have this hunch that there was a way to accumulate offsets from
a scan or gsub operation, but I can't come up with it.

Like this?

irb(main):017:0> str = "abcdbcdae"
=> "abcdbcdae"
irb(main):018:0> ind = Hash.new {|h,k| h[k]=}
=> {}
irb(main):019:0> str.scan(/./) {|c| ind[c] << $`.length}
=> "abcdbcdae"
irb(main):020:0> ind
=> {"a"=>[0, 7], "b"=>[1, 4], "c"=>[2, 5], "d"=>[3, 6], "e"=>[8]}

It may well have been that, or something like it.

David

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

I apologise for the complete ugliness of this code :slight_smile:

Look away of you're screamish!

ARGV.to_s.split(/\s*/).map{|x|x.downcase}.inject(Hash.new(0)){|h,x|h[x]
+=1 and h}.each{|i,h| print "#{i}(#{h}), "}

Foobar, output:

a(1), b(1), o(2), f(1), r(1)

Whoops, I didn't read the question properly, this prints all
occurances, not positions..