2017-03-03 201 views
0

訪問值我建立紅寶石 - 從JSON數組

def create_fields fields 
    fields_list = [] 

    fields.each do |field| 
    # puts "adding_field to array: #{field}" 
    field_def = { field: field, data: { type: 'Text', description: '' } } 
    fields_list.push field_def 
    end 
    fields_list 
end 

fields_list被設置爲一個jsonb字段字段的數組。

可以說,我通過在

create_fields ['Ford', 'BMW', 'Fiat'] 

JSON結果是一個數組:

{"field"=>"Ford", "data"=>{"type"=>"Text", "description"=>""}} 
{"field"=>"BMW", "data"=>{"type"=>"Text", "description"=>""}} 
{"field"=>"Fiat", "data"=>{"type"=>"Text", "description"=>""}} 

如何從JSON數組訪問 '福特'?我錯誤地創建了數組嗎?有沒有更好的方法來創建這個數組,所以我可以訪問我想要的字段?

這種說法通過assert_equal(3, fields.count)

但是我想「福特」,並檢查它的屬性,例如type ='Text',type可以等於'Number'或其他。

+1

你能澄清一下你真正想做的事?本田沒有包含在這裏的任何數組中,所以我想知道當它不存在時如何訪問它? – oreoluwa

+0

你確定你的數組包含'field'的hash:'Honda'? –

+0

@oreoluwa對不起,我的意思是福特。 – Haroon

回答

4

您的結果create_fiel DS方法使用指定的參數如下:

[ 
    {:field=>"Ford", :data=>{:type=>"Text", :description=>""}}, 
    {:field=>"BMW", :data=>{:type=>"Text", :description=>""}}, 
    {:field=>"Fiat", :data=>{:type=>"Text", :description=>""}} 
] 

這意味着,如果你想訪問屬於「福特」行了,你需要尋找它喜歡:

2.3.1 :019 > arr.select{|e| e[:field] == "Ford" } 
=> [{:field=>"Ford", :data=>{:type=>"Text", :description=>""}}] 
2.3.1 :020 > arr.select{|e| e[:field] == "Ford" }[0][:data][:type] 
=> "Text" 

這不是最優的,因爲你需要搜索一個數組O(n)而不是使用散列表的專業人員。如果有例如:2個「福特」線,則會得到一個包含2個元素的數組,難以處理字段值中的衝突。

這將是更好,如果你創建喜歡的數組:

def create_fields fields 
    fields_list = [] 

    fields.each do |field| 
    # puts "adding_field to array: #{field}" 
    field_def = [field, { type: 'Text', description: '' } ] 
    fields_list.push field_def 
    end 
    Hash[fields_list] 
end 

如果你選擇了這個版本,您可以訪問諸如成員:

2.3.1 :072 > arr = create_fields ['Ford', 'BMW', 'Fiat'] 
=> {"Ford"=>{:type=>"Text", :description=>""}, "BMW"=>{:type=>"Text", :description=>""}, "Fiat"=>{:type=>"Text", :description=>""}} 
2.3.1 :073 > arr["Ford"] 
=> {:type=>"Text", :description=>""} 
2.3.1 :074 > arr["Ford"][:type] 
=> "Text" 

上述兩個例子是紅寶石詞典/哈希。 如果你想創建這樣一個JSON,你需要將它轉換:

2.3.1 :077 > require 'json' 
=> true 
2.3.1 :078 > arr.to_json 
=> "{\"Ford\":{\"type\":\"Text\",\"description\":\"\"},\"BMW\":{\"type\":\"Text\",\"description\":\"\"},\"Fiat\":{\"type\":\"Text\",\"description\":\"\"}}" 
+0

有一件事可以幫助簡化'create_fields'方法,就是做像你這樣的映射:'Hash [fields.map {[field,{...}]}]'儘管散佈在多個可讀性中。你在那裏有正確的想法,但是創建一箇中間變量並推送到臨時數組實際上是不必要的。 – tadman

+0

葉普,你是對的。有更短和更有效的方式來做這種轉換。我可以從一開始就使用'{}'並設置其元素。儘管如此,這需要很少的修改 – akg

+0

你也可以用'detect'方法來代替'select' :) –

1

所以,你有你的方法的結果是:

result = 
    [ 
    {"field"=>"Ford", "data"=>{"type"=>"Text", "description"=>""}}, 
    {"field"=>"BMW", "data"=>{"type"=>"Text", "description"=>""}}, 
    {"field"=>"Fiat", "data"=>{"type"=>"Text", "description"=>""}} 
    ] 

從中獲得「福特」,你可以用簡單的方法detect

result.detect { |obj| obj['field'] == 'Ford' } 
#=> { "field"=>"Ford", "data"=>{"type"=>"Text", "description"=>""} 

此外,我建議你修改你的方法,使它更具可讀性:

def create_fields(fields) 
    fields.map do |field| 
    { 
     field: field, 
     data: { 
     type: 'Text', 
     description: '' 
     } 
    } 
    end 
end 
3

這是更有意義,我要基於已知鍵訪問值的結構:

def create_fields fields 
    fields_hash = {} 

    fields.each do |field| 
    fields_hash[field] = {type: 'Text', description: ''} 
    end 
    fields_hash 
end 

# The hash for fields_hash will look something like this: 
{ 
    Ford: { 
    type: "Text", 
    description: "" 
    }, 
    BMW: {...}, 
    Fiat: {...} 
} 

這將允許您訪問如下所示的值:Ruby中的fields[:Ford][:type]和JSON中的fields.Ford.type。聽起來像返回一個Object而不是一個Array更容易。您可以通過這種方式更輕鬆地訪問基於鍵的值,並且仍然可以選擇循環瀏覽對象。

1

顯然,有幾種創建或訪問數據的方式,但我總是傾向於選擇最適合您的應用程序的數據結構。 在你目前的情況下,爲了訪問Ford哈希值,你可以使用紅寶石Array#detect方法,例如:

ford = fields_list.detect{|field_hash| field_hash['field'] == 'Ford' } 
ford['data'] # => {"type"=>"Text", "description"=>""} 
ford['data']['type'] # => 'Text'