Reza
Reza

Reputation: 3038

Extract ruby hash element value from an array of objects

I've got the following array

[#<Attachment id: 73, container_id: 1, container_type: "Project", filename: "Eumna.zip", disk_filename: "140307233750_Eumna.zip", filesize: 235303, content_type: nil, digest: "9a10843635b9e9ad4241c96b90f4d331", downloads: 0, author_id: 1, created_on: "2014-03-07 17:37:50", description: "", disk_directory: "2014/03">, #<Attachment id: 74, container_id: 1, container_type: "Project", filename: "MainApp.cs", disk_filename: "140307233750_MainApp.cs", filesize: 1160, content_type: nil, digest: "6b985033e19c5a88bb5ac4e87ba4c4c2", downloads: 0, author_id: 1, created_on: "2014-03-07 17:37:50", description: "", disk_directory: "2014/03">]

I need to extract the value 73 and 74 from this string which is Attachment id.

is there any way to extract this value

Upvotes: 1

Views: 1716

Answers (3)

Cary Swoveland
Cary Swoveland

Reputation: 110675

The elements of the array (I'll call it a) look like instances of the class Attachment (not strings). You can confirm that by executing e.class in IRB, where e is any element a (e.g., a.first). My assumption is correct if it returns Attachment. The following assumes that is the case.

@Arup shows how to retrieve the values of the instance variable @id when it has an accessor (for reading):

a.map(&:id)

(aka collect). You can see if @id has an accessor by executing

e.instance_methods(false)

for any element e of a. This returns an array which contains all the instance methods defined for the class Attachment. (The argument false causes Ruby's built-in methods to be excluded.) If @id does not have an accessor, you will need to use Object@instance_variable_get:

a.map { |e| e.instance_variable_get(:@id) }

(You could alternatively write the argument as a string: "@id").

If

s = '[#<Attachment id: 73, container_id: 1,..]'

in fact a string, but you neglected to enclose it in (single) quotes, then you must execute

a = eval(s)

to convert it to an array of instances of Attachment before you can extract the values of :@a.

Hear that 'click'? That was me starting my stop watch. I want to see how long it will take for a comment to appear that scolds me for suggesting the use of (the much-maligned) eval.

Two suggestions: shorten code to the essentials and avoid the need for readers to scroll horizontally to read it. Here, for example, you could have written this:

a = [#<Attachment id: 73, container_id: 1>, #<Attachment id: 74, container_id: 1>]

All the instance variables I've removed are irrelevant to the question.

If that had been too long to fit on one lines (without scrolling horizontally, write it as:

a = [#<Attachment id: 73, container_id: 1>,
     #<Attachment id: 74, container_id: 1>]

Lastly, being new to SO, have a look at this guide.

Upvotes: 1

Arup Rakshit
Arup Rakshit

Reputation: 118261

Do as below using Array#collect:

array.collect(&:id)

In case it is a string use JSON::parse to get the array back from the string first, then use Array#collect method as below :

require 'json'
array = JSON.parse(string)
array.collect(&:id)

Upvotes: 1

Vlad Khomich
Vlad Khomich

Reputation: 5880

just in case author meant he has an actual String instance:

string = '[#<Attachment id: 73, container_id: 1, container_type: "Project", filename: "Eumna.zip", disk_filename: "140307233750_Eumna.zip", filesize: 235303, content_type: nil, digest: "9a10843635b9e9ad4241c96b90f4d331", downloads: 0, author_id: 1, created_on: "2014-03-07 17:37:50", description: "", disk_directory: "2014/03">, #<Attachment id: 74, container_id: 1, container_type: "Project", filename: "MainApp.cs", disk_filename: "140307233750_MainApp.cs", filesize: 1160, content_type: nil, digest: "6b985033e19c5a88bb5ac4e87ba4c4c2", downloads: 0, author_id: 1, created_on: "2014-03-07 17:37:50", description: "", disk_directory: "2014/03">]'

string.scan(/\sid: (\d+)/).flatten => ["73", "74"]

Upvotes: 2

Related Questions