# String Indexing

**URL:** <https://www.ruby-forum.com/t/string-indexing/168071>\
**Category:** Ruby\
**Created:** [May 15, 2009, 2:05pm UTC](https://www.ruby-forum.com/t/string-indexing/168071 "2009-05-15T14:05:24Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![rubist](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/c67d28/32.png) [@rubist](https://www.ruby-forum.com/u/rubist)\
**Post date:** [May 15, 2009, 2:05pm UTC](https://www.ruby-forum.com/t/string-indexing/168071/1 "2009-05-15T14:05:24Z")

</div>

Hi all,

I have a piece of data like so:

aaaaaaa  
bbbbbbb  
ccccccc  
123  
ddddddd  
yes  
eeeeeee

I need to find the string yes and the string 123, however I first have  
to find the string yes. I have this code to do this task:

stack = “aaaaaaa  
bbbbbbb  
ccccccc  
123  
ddddddd  
yes  
eeeeeee”

string = “yes”  
stack.each do |c|  
c.each {|line|  
line.chomp!;  
puts line.strip! if line.include? string}  
end

How can I then, using ‘yes’ as my index to find the string ‘123’?  
Basically I need to first find ‘yes’ and once discovered, search back to  
find ‘123’. I hoep I explained it well enough.

I have thought about using pop, to pop the values off from an array but  
I am not sure how to do this.

Could someone please give me a pointer to achieve this?

Thanks!

---

<div class="post-metadata">

**Author:** ![rubist](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/c67d28/32.png) [@rubist](https://www.ruby-forum.com/u/rubist)\
**Post date:** [May 15, 2009, 2:40pm UTC](https://www.ruby-forum.com/t/string-indexing/168071/2 "2009-05-15T14:40:50Z")

</div>

Ruby L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> eeeeeee  
> yes  
> How can I then, using ‘yes’ as my index to find the string ‘123’?  
> Basically I need to first find ‘yes’ and once discovered, search back to  
> find ‘123’. I hoep I explained it well enough.
> 
> I have thought about using pop, to pop the values off from an array but  
> I am not sure how to do this.
> 
> Could someone please give me a pointer to achieve this?

Just do it.

(stack = “aaaaaaa  
bbbbbbb  
123 nay!  
ccccccc  
123 yeah!  
ddddddd  
yes yes  
yes no  
eeeeeee”)  
(string1 = “123”)  
(string2 = “yes”)  
(match1 = “”)  
(match2 = “”)  
(stack . each { |line|  
(line . chomp!)  
((match1 = line) if (line . include? string1))  
(if (line . include? string2)  
(match2 = line)  
(break)  
end)})  
(printf “one=%s\ntwo=%s\n” , match1 , match2)

one=123 yeah!  
two=yes yes

---

<div class="post-metadata">

**Author:** ![rubist](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/c67d28/32.png) [@rubist](https://www.ruby-forum.com/u/rubist)\
**Post date:** [May 15, 2009, 3:10pm UTC](https://www.ruby-forum.com/t/string-indexing/168071/3 "2009-05-15T15:10:33Z")

</div>

Pascal J. Bourguignon wrote:

> Ruby L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> one=123 yeah!  
> two=yes yes

Hi, thanks for the great, simple solution!!

The problem for me is that I do not know what the second value I am  
looking for is… 🙂

I am making an HTTP request to a site and I know one value to look for.  
The value I am interested in changes but is always 2 lines above the  
string I CAN find.

This code works: #if I want to retrieve ‘a’

data = [‘a’,‘b’,‘c’]  
found = data.index(‘c’)  
puts data[found-2]

Sadly I need it to work on a HTTP request so I store my data liek this:

got = Array.new  
go = net::HTTP.new(a,b)  
…  
got = go.get(‘some\_path’)  
…  
i = got.index(‘some known string’)  
puts got[i-2] #print the secret string 2 lines above

In theory in my mind I can make it work, but in code, I can’t/

I get an error:

undefined method `index’ for #\<Net::HTTPOK 200 OK readbody=true\>  
(NoMethodError)

Thanks for spending time looking at my post.

---

<div class="post-metadata">

**Author:** ![rubist](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/c67d28/32.png) [@rubist](https://www.ruby-forum.com/u/rubist)\
**Post date:** [May 15, 2009, 3:47pm UTC](https://www.ruby-forum.com/t/string-indexing/168071/4 "2009-05-15T15:47:19Z")

</div>

On May 15, 8:40 am, removed\_email\_address@domain.invalid (Pascal J. Bourguignon)  
wrote:

> ```
> (@tail = (Node . new data))
> 
> ```

This is one of my favorite lines of Pascal code.

> ```
> (@tail . next= @tail)
> 
> ```

This is also good.

Pascal, why again do you use Ruby if you obviously hate it so much?

---

<div class="post-metadata">

**Author:** ![rubist](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/c67d28/32.png) [@rubist](https://www.ruby-forum.com/u/rubist)\
**Post date:** [May 15, 2009, 3:40pm UTC](https://www.ruby-forum.com/t/string-indexing/168071/5 "2009-05-15T15:40:50Z")

</div>

Ruby L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> found = data.index(‘c’)  
> puts data[found-2]

Well if the data you want to extract is two lines above the line you  
match, why didn’t you say so sooner? You told only us about “123” and  
“yes”…

But on the same principle, you may keep a buffer of the last lines  
seen to be able to go back easily:

(stack = “aaaaaaa  
bbbbbbb  
123 nay!  
ccccccc  
123 yeah!  
ddddddd  
yes yes  
yes no  
eeeeeee”)  
(target = “yes”)  
(previousLines = (CircularBuffer . new(2)))  
(stack . each { |line|  
(line . chomp!)  
(if (line . include? target)  
(break)  
end)  
(previousLines . enter line)})  
(printf “two lines before the target line is ‘%s’\n” , (previousLines .  
nth 1))

Here is for example a CircularBuffer that would do:

(class Node  
(attr\_accessor :data,:previous,:next)  
(def initialize(data)  
(@data = data)  
(@previous = nil)  
(@next = nil)  
end)  
end)

(class CircularBuffer  
(def initialize(maxSize)  
(@maxSize = maxSize)  
(@size = 0)  
(@tail = nil)  
end)  
(def enter(data)  
(if (@size == @maxSize)  
(@tail . data= data)  
(@tail = (@tail . next))  
elsif (@size == 0)  
(@tail = (Node . new data))  
(@tail . previous= @tail)  
(@tail . next= @tail)  
(@size = 1)  
else  
(node = (Node . new data))  
(node . previous= (@tail . previous))  
(node . next= @tail)  
(@tail . previous . next = node)  
(@tail . previous = node)  
(@size = (@size + 1))  
end)  
end)  
(def nth(index)  
(index = (index . modulo @maxSize))  
(cur = (@tail . previous))  
(while (0 \< index)  
(cur = (cur . previous))  
(index = (index - 1))  
end)  
(cur . data)  
end)  
end)

> Sadly I need it to work on a HTTP request so I store my data liek this:
> 
> got = Array.new  
> go = net::HTTP.new(a,b)

However, if your data is HTML or XML, this kind of data is structured,  
and newlines are rather insignificant, so it’s brittle to count lines  
to find data there. You should rather parse the html (there are Ruby  
libraries to do that), and find your data “structurally”.
