简体   繁体   中英

Ruby on Rails: Array to Hash with (key, array of values)

Lets say I have an Array of content_categories (content_categories = user.content_categories)

I now want to add every element belonging to a certain categorie to content_categories with the category as a key and the the content-item IDs as elements of a set

In PHP something like this is possible:

foreach ($content_categories as $key => $category) {
  $contentsByCategoryIDArray = Category.getContents($category[id])  
  $content_categories[$key][$contentsByCategoryIDArray]
}

Is there an easy way in rails to do this?

Greets,

Nico

Your question isn't really a Rails question, it's a general Ruby programming question.

Your description isn't very clear, but from what I understand, you want to group IDs for common categories using a Hash. There are various other ways of doing this, but this is easy to understand::

ary = [
  'cat1', {:id => 1},
  'cat2', {:id => 2},
  'cat1', {:id => 3}
]

hsh = {}
ary.each_slice(2) { |a| 
  key,category = a
  hsh[key] ? hsh[key] << category[:id] : hsh[key] = [category[:id]]
}
hsh # => {"cat1"=>[1, 3], "cat2"=>[2]}

I'm using a simple Array with a category, followed by a simple hash representing some object instance, because it makes it easy to visualize. If you have a more complex object, replace the hash entries with those objects, and tweak how you access the ID in the ternary ( ?: ) line.

Using Enumerable.inject():

hsh = ary.each_slice(2).inject({}) { |h,a| 
  key,category = a
  h[key] ? h[key] << category[:id] : h[key] = [category[:id]]
  h 
}
hsh # => {"cat1"=>[1, 3], "cat2"=>[2]}

Enumerable.group_by() could probably shrink it even more, but my brain is fading.

我使用Enumerable #injection

content_categories = content_categories_array.inject({}){ |memo, category| memo[category] = Category.get_contents(category); memo }
Hash[content_categories.map{|cat|
  [cat, Category.get_contents(cat)]
}]

不是真正正确的答案,因为你需要你的数组中的ID,但我仍然发布它,因为它很好而且简短,你可能真的侥幸逃脱它:

content_categories.group_by(&:category)
content_categories.each do |k,v|
  content_categories[k] = Category.getContents(v)
end

I suppose it's works

If i understand correctly, content_categories is an array of categories, which needs to be turned into a hash of categories, and their elements.

content_categories_array = content_categories
content_categories_hash = {}
content_categories_array.each do |category| 
  content_categories_hash[category] = Category.get_contents(category)
end
content_categories = content_categories_hash

That is the long version, which you can also write like

content_categories = {}.tap do |hash|
  content_categories.each { |category| hash[category] = Category.get_contents(category) }
end 

For this solution, content_categories must be a hash, not an array as you describe. Otherwise not sure where you're getting the key.

contents_by_categories = Hash[*content_categories.map{|k, v| [k, Category.getContents(v.id)]}]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM