[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Extracting a value from an array

Albert Schlef

5/2/2008 9:03:00 AM

I have the following array:

headers = [
{ :name => 'user-agent', :value => 'blah blah' },
{ :name =>'content-type', :value => 'text/html' },
{ :name => 'pragma', :value => 'no-cache' },
{ :name =>'content-length', :value => '30' },
{ :name =>'content-type', :value => 'text/html' },
]

Now, I want to extract the :value of the first header of a specific
:name. For example, I want to extract the :value of the 'content-type'
header.

So I do:

content_length = nil
headers.each { |header|
content_length = header[:value] if header[:name] == 'content-length'
}

However, this code is not very "beautiful", and I was wondering if
there's some other, more clearer way to do this.

(And it's fine with me if we take the :value of a 'content-type' header
which is not necessarily the first in the array (in the code above I
actually pick the last header). Also, I don't very much mind about
performance because there are a few headers. I'm simply looking for a
clear, straightforward code for this simple task.)
--
Posted via http://www.ruby-....

17 Answers

Jano Svitok

5/2/2008 9:27:00 AM

0

On Fri, May 2, 2008 at 11:02 AM, Albert Schlef <albertschlef@gmail.com> wrote:
> I have the following array:
>
> headers = [
> { :name => 'user-agent', :value => 'blah blah' },
> { :name =>'content-type', :value => 'text/html' },
> { :name => 'pragma', :value => 'no-cache' },
> { :name =>'content-length', :value => '30' },
> { :name =>'content-type', :value => 'text/html' },
> ]
>
> Now, I want to extract the :value of the first header of a specific
> :name. For example, I want to extract the :value of the 'content-type'
> header.
>
> So I do:
>
> content_length = nil
> headers.each { |header|
> content_length = header[:value] if header[:name] == 'content-length'
> }
>
> However, this code is not very "beautiful", and I was wondering if
> there's some other, more clearer way to do this.
>
> (And it's fine with me if we take the :value of a 'content-type' header
> which is not necessarily the first in the array (in the code above I
> actually pick the last header). Also, I don't very much mind about
> performance because there are a few headers. I'm simply looking for a
> clear, straightforward code for this simple task.)

headers.select {|header| header[:name] == 'content-length'}.first[:value]

or even better:

headers.find {|header| header[:name] == 'content-length'}[:value]

Sandro Paganotti

5/2/2008 9:27:00 AM

0

I've compressed your loop into this:

(headers.select{ |h| h[:name] == 'content-length' }.first)[:value]

On Fri, May 2, 2008 at 9:02 AM, Albert Schlef <albertschlef@gmail.com> wrote:
> I have the following array:
>
> headers = [
> { :name => 'user-agent', :value => 'blah blah' },
> { :name =>'content-type', :value => 'text/html' },
> { :name => 'pragma', :value => 'no-cache' },
> { :name =>'content-length', :value => '30' },
> { :name =>'content-type', :value => 'text/html' },
> ]
>
> Now, I want to extract the :value of the first header of a specific
> :name. For example, I want to extract the :value of the 'content-type'
> header.
>
> So I do:
>
> content_length = nil
> headers.each { |header|
> content_length = header[:value] if header[:name] == 'content-length'
> }
>
> However, this code is not very "beautiful", and I was wondering if
> there's some other, more clearer way to do this.
>
> (And it's fine with me if we take the :value of a 'content-type' header
> which is not necessarily the first in the array (in the code above I
> actually pick the last header). Also, I don't very much mind about
> performance because there are a few headers. I'm simply looking for a
> clear, straightforward code for this simple task.)
> --
> Posted via http://www.ruby-....
>
>



--
Go outside! The graphics are amazing!

7stud --

5/2/2008 9:33:00 AM

0

Albert Schlef wrote:
> I have the following array:
>
> headers = [
> { :name => 'user-agent', :value => 'blah blah' },
> { :name =>'content-type', :value => 'text/html' },
> { :name => 'pragma', :value => 'no-cache' },
> { :name =>'content-length', :value => '30' },
> { :name =>'content-type', :value => 'text/html' },
> ]
>
> Now, I want to extract the :value of the first header of a specific
> :name. For example, I want to extract the :value of the 'content-type'
> header.
>
> So I do:
>
> content_length = nil
> headers.each { |header|
> content_length = header[:value] if header[:name] == 'content-length'
> }
>
> However, this code is not very "beautiful", and I was wondering if
> there's some other, more clearer way to do this.
>
> (And it's fine with me if we take the :value of a 'content-type' header
> which is not necessarily the first in the array (in the code above I
> actually pick the last header). Also, I don't very much mind about
> performance because there are a few headers. I'm simply looking for a
> clear, straightforward code for this simple task.)

headers = [
{ :name => 'user-agent', :value => 'blah blah' },
{ :name =>'content-type', :value => 'text/html' },
{ :name => 'pragma', :value => 'no-cache' },
{ :name =>'content-length', :value => '30' },
{ :name =>'content-type', :value => 'text/html' },
]

content_type = ""

headers.each do |hash|
if hash[:name] == "content-type"
content_type = hash[:value]
break
end
end

puts content_type
--
Posted via http://www.ruby-....

7stud --

5/2/2008 9:34:00 AM

0

Sandro Paganotti wrote:
> I've compressed your loop into this:
>
> (headers.select{ |h| h[:name] == 'content-length' }.first)[:value]

That seems pretty typical of ruby programmers: cram everything into one
line and call it "clear".
--
Posted via http://www.ruby-....

Arlen Cuss

5/2/2008 10:08:00 AM

0

[Note: parts of this message were removed to make it a legal post.]

Hi,

On Fri, May 2, 2008 at 7:34 PM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:

> > I've compressed your loop into this:
> >
> > (headers.select{ |h| h[:name] == 'content-length' }.first)[:value]
>
> That seems pretty typical of ruby programmers: cram everything into one
> line and call it "clear".
>

It's still done in a very neat fashion, and the one that makes the most
sense from a functional programming point of view.

Speaking as objectively as possible, it's better than perhaps your proposal
since it accurately shows what we're doing (`selecting' item hs where the
[:name] is 'content-length', then picking the `first' and getting the
[:value]..), and doesn't rely on creating new local variables.

Arlen

Todd Benson

5/2/2008 11:12:00 AM

0

On Fri, May 2, 2008 at 4:34 AM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:
> Sandro Paganotti wrote:
> > I've compressed your loop into this:
> >
> > (headers.select{ |h| h[:name] == 'content-length' }.first)[:value]
>
> That seems pretty typical of ruby programmers: cram everything into one
> line and call it "clear".

It looks a lot cleaner to me than using 'break'.

Todd

James Gray

5/2/2008 12:29:00 PM

0

On May 2, 2008, at 5:07 AM, Arlen Cuss wrote:

> Hi,
>
> On Fri, May 2, 2008 at 7:34 PM, 7stud -- <bbxx789_05ss@yahoo.com>
> wrote:
>
>>> I've compressed your loop into this:
>>>
>>> (headers.select{ |h| h[:name] == 'content-length' }.first)[:value]
>>
>> That seems pretty typical of ruby programmers: cram everything into
>> one
>> line and call it "clear".
>>
>
> It's still done in a very neat fashion, and the one that makes the
> most
> sense from a functional programming point of view.

Well, the find() iterator makes the most sense, I would say.
select().first() is just a hand-rolled find() that's slower to run and
takes more memory, of course. ;)

The archives should give readers plenty of evidence regarding how much
attention should be given to 7stud's Ruby opinions though.

James Edward Gray II


Albert Schlef

5/2/2008 1:06:00 PM

0

Thanks you all for these snippets.

However, the snippets you gave me may fail, because there's one detail I
neglected to mention --as I thought it was obvious from my code:

The 'content-type' header may be missing. That's because servers don't
always return it: in '302 redirect' replies there isn't a 'content-type'
at all.

The problem with the snippets I was given here is that they
unconditionaly do [:value] on some expression. When the 'content-type'
is missing, the expression is 'nil', and since the [] method isn't
defined for NilClass, the code fails with an exception.

I know I can change your "some_expression.first[:value]" to
"(some_expression || {}).first[:value]" and then things would work. OK.
But I wondered if there's some nifty solution. I don't mind seeing a
Ruby 1.9 only solution (or a Ruby 2.0 one) --though I'm using 1.8, this
question is mostly to satisfy my curiosity.
--
Posted via http://www.ruby-....

Albert Schlef

5/2/2008 1:08:00 PM

0


> I know I can change your "some_expression.first[:value]" to
> "(some_expression || {}).first[:value]" and then things would work. OK.

A typo. I meant "((some_expression).first || {})[:value]".
--
Posted via http://www.ruby-....

Luc Heinrich

5/2/2008 1:32:00 PM

0

On 2 mai 08, at 15:05, Albert Schlef wrote:

> I know I can change your "some_expression.first[:value]" to
> "(some_expression || {}).first[:value]" and then things would work.
> OK.
> But I wondered if there's some nifty solution.

How about this:

content_type_header = lambda { |h| h[:name] == 'content-type' }
content_type = headers.find(&content_type_header).fetch(:value) if
headers.any?(&content_type_header)

--
Luc Heinrich - luc@honk-honk.com