Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
This post was edited and submitted for review 5 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I have an array of hashes:
my_array = [
{
:id => 1,
:name => "Bill"
},
{
:id => 2,
:name => "Joe"
},
{
:id => 3,
:name => "Bob"
}
]
How can I get an item passing the ID, for example, given 3 as the 'id' I'd like to get the hash: {"id": 3, "nome": "Bob"}.
UPDATE:
I discovered the answer, using the method .selec as follows:
my_array.select { |a| a[:id] == 1 }
What you have is a JSON string. You will need to parse it into an array of hashes first and then use Enumerable#find to get the item:
require 'json'
test = '[
{
"id": 1,
"nome": "Bill"
},
{
"id": 2,
"nome": "Joe"
},
{
"id": 3,
"nome": "Bob"
}
]'
# Parse into an array of hashes
hashes = JSON.parse(test)
foundItem = hashes.find { |item| item["id"] == 3}
puts foundItem
Since it looks like jSON you should parse as above if it is an actual array of Hashes you can do this
arr = [{"id" => 1,"nome"=> "Bill"},{"id"=> 2,"nome"=> "Joe"},{"id"=> 3,"nome"=> "Bob"}]
arr.select{|h| h["id"] == 3}
#=>[{"id"=> 3,"nome"=> "Bob"}]
This will return an Array of all matching Hash
To get a single value you can use
arr.select{|h| h["id"] == 3}.pop
#=>{"id"=> 3,"nome"=> "Bob"}
Which will return the last matching Hash Or as #KalmanHazins stated
arr.find{|h| h["id"] == 3}
#=>{"id"=> 3,"nome"=> "Bob"}
Which will return the first Hash that matches based on current order
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
In Ruby, what would be the best way to sort an array of objects by an order property that may or may not exist, and if it doesn't, then fall back to sorting based on a property named title?
Not sure if this is what you are after, but a quick solution could be:
arr = [{a:"never", b:"anna"}, {a:"always", b:"bob"}, {b:"colin"}, {b:"abe"}]
arr.sort_by! {|o| o[:a] ? o[:a] : o[:b] }
#=> [{:b=>"abe"}, {:a=>"always", :b=>"bob"}, {:b=>"colin"}, {:a=>"never", :b=>"anna"}]
Here's how to perform a sort with a fallback in Ruby:
Item = Struct.new(:order, :title)
items = [
Item.new(nil, "d"),
Item.new(nil, "b"),
Item.new(1, "a"),
Item.new(3, "c"),
Item.new(2, "e")
]
sorted_items = items.sort do |a, b|
if a.order && b.order
a.order <=> b.order
elsif a.order || b.order
# This prioritizes all items with an order
a.order ? -1 : 1
else
a.title.to_s <=> b.title.to_s
end
end
require 'awesome_print'
ap sorted_items
# [
# [0] {
# :order => 1,
# :title => "a"
# },
# [1] {
# :order => 2,
# :title => "e"
# },
# [2] {
# :order => 3,
# :title => "c"
# },
# [3] {
# :order => nil,
# :title => "b"
# },
# [4] {
# :order => nil,
# :title => "d"
# }
# ]
Let me also say that if you are fetching records from a database, then it would be better to do the sorting in your SQL query. If Item was an ActiveRecord model, you could do something like:
Item.order('order ASC NULLS LAST, title ASC')
(NULLS LAST can be used in Postgres, check out this answer for MySQL.)
If I understand you right here is how to do this:
arr1 = [{order: 1, title: 2},{title: 4},{order: 2, title: 1}]
arr2 = [{order: 1, title: 2},{order: 7, title: 4},{order: 2, title: 1}]
def sort_it prop1, prop2, ar
ar.map{|el| el[prop1]}.include?(nil) ?
ar.sort_by{|el| el[prop2]}
:
ar.sort_by{|el| el[prop1]}
end
p sort_it(:order, :title, arr1)
p sort_it(:order, :title, arr2)
Which gives:
#=> [{:order=>2, :title=>1}, {:order=>1, :title=>2}, {:title=>4}]
#=> [{:order=>1, :title=>2}, {:order=>2, :title=>1}, {:order=>7, :title=>4}]
So, the algorythm is simple: select all objects' properties (:order in our case) and if output temporary array contains at least one nil then sort by second given property, otherwise -- by first.
You could try
def sort_array(array)
sort_by_property_name = sort_by_property_present?(array, :order, :title)
array.sort_by { |ob| ob.public_send(sort_by_property_name) }
end
def sort_by_property_present?(array, primary_name, fallback_name)
array.all? { |ob| ob.respond_to?(name) } || return fallback_name
primary_name
end
Assuming you want to sort based on field/parameter that may or may not be present, I am assuming:
When the parameter is present sort by it.
When unavailable fall back to the next parameter.
Please review the following code that can sort an object array based on a number of fields, the system keeps falling back to the next field if the field is unavailable. Its developed with the assumption that the last field will definitely be present.
class CondtionalSort
def run(array: a, keys_to_order_by: keys)
array.sort do |e1, e2|
keys_to_order_by.each do |key|
break e1[key] <=> e2[key] if (e1.key?(key) && e2.key?(key))
end
end
end
end
ArrayTest = [{order: 1, title: 2},{title: 4},{order: 2, title: 1}]
ArrayTest_SORTED = [{:order=>1, :title=>2}, {:order=>2, :title=>1}, {:title=>4}]
sorter = CondtionalSort.new
sorter.run array: ArrayTest, keys_to_order_by: [:order, :title]
I just use an array as the sort_by:
# sample data:
Item = Struct.new(:property1, :property2, :property3)
collection = [Item.new("thing1", 3, 6), Item.new("thing1", 3, 1), Item.new("aaa", 1,1) ]
# sort
collection.sort_by{|item| [item.property1, item.property2, item.property3] }
# => [#<struct Item property1="aaa", property2=1, property3=1>,
#<struct Item property1="thing1", property2=3, property3=1>,
#<struct Item property1="thing1", property2=3, property3=6>]
This question already has answers here:
Converting a nested hash into a flat hash
(8 answers)
Closed 8 years ago.
Here is a structure of hash of arrays:
[
{
"key1" => [
"value1",
{"key2" => ["value2"]},
{"key3" => [
"value3",
{
"key4" => "value4"
}
]
}
]
},
{
"anotherKey1" => [],
}
]
I want desired output for that structure like filepaths:
/key1/value1
/key1/key2/value2
/key3/value3
/key3/key4/value4
How can I do that without inventing a wheel? Simple recursion could help, but is there any ready-to-go modules?
I do not think you would be reinventing any wheels to do this. You would like to traverse a nested structure of arrays and hashes and react completely different to the elements depending on whether something is an Array or a Hash. No library function is going to do exactly that for you, as you would need to vary more than one thing with blocks in order to be as flexible as you might like to be.
In short: write your recursive function to do this.
(Btw: The top level of your data structure is an array of hashes, not a hash of arrays …)
I decided to write my own wheel (thanks for Patru, vote up).
And I have this function:
def flat_hash_of_arrays(hash,string = "",delimiter="/",result = [])
# choose delimiter
hash.each do |key,value|
# string dup for avoid string-reference (oh, Ruby)
newString = string + delimiter + key
# if value is array
if value.is_a?(Array)
# if array not empty
value.each do |elementOfArray|
# if a string, I dont need recursion, hah
if elementOfArray.is_a?(String)
resultString = newString + delimiter + elementOfArray
# add new object
result << resultString
end
# if a hash, I need recursion
if elementOfArray.is_a?(Hash)
flat_hash_of_arrays(elementOfArray,newString,delimiter,result)
end
end
end
end
end
and test it:
flatten_hash = {
"key1" => [
"value1",
{"key2" => ["value2"]},
{"key3" => [
"value3",
{
"key4" => "value4"
}
]
},
"value4",
{
"key4" => ["value5"],
}
]
}
result = []
flat_hash_of_arrays(flatten_hash,"","/",result)
puts result
output is:
/key1/value1
/key1/key2/value2
/key1/key3/value3
/key1/value4
/key1/key4/value5
fine!
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am trying to remove partial duplicate value from an Array.
['John', 'Johnson', 'Mike', 'Tim', 'Timberland']
I want remove partial duplicate value.
in this case, I want keep longer string value.
['Johnson', 'Mike', 'Timberland']
Any good idea?
This is how I would do:
ary = ['John', 'Johnson', 'Mike', 'Tim', 'Timberland']
ary.select {|e| ary.grep(Regexp.new(e)).size == 1 }
# => ["Johnson", "Mike", "Timberland"]
Just do the following, in case when part is resided at the beginning of a word only:
array = ['John', 'Johnson', 'Mike', 'Tim', 'Brakatim', 'Weltimwel']
# => ["John", "Johnson", "Mike", "Tim", "Brakatim", "Weltimwel"]
array.reject {| v | " #{array.join( ' ' )} " =~ /\W#{v}\w/i }
# => ["Johnson", "Mike", "Tim", "Brakatim", "Weltimwel"]
Or in case when part is resided at the beginning of a word, and at the end or middle of it:
array = ['John', 'Johnson', 'Mike', 'Tim', 'Timberland', 'Brakatim', 'Weltimwel']
# => ["John", "Johnson", "Mike", "Tim", "Timberland", "Brakatim", "Weltimwel"]
array.reject {| v | " #{array.join( ' ' )} " =~ /\W#{v}\w|\w#{v}\W|\w#{v}\w/i }
# => ["Johnson", "Mike", "Timberland", "Brakatim", "Weltimwel"]
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have this array of arrays:
[["abc", "123"], ["cde", "456"], ["cde", "674"]]
And I want this array of arrays arranged in this way:
{ "name": "test", "children": [ {"name": "abc", "children": [ {"name": "123"} ]}, {"name": "cde", "children": [ { "name": "456"},{"name": "674"} ]}]}
How can I make this transformation in ruby language?
Thanks in advance.
Try this
require 'json'
src_arr= [["abc", "123"], ["cde", "456"], ["cde", "674"]]
tmp = {} # to collect all common node first
src_arr.each do |arr|
if node = tmp[arr.first] # check if node exists
node['children'] << {'name' => arr.last} # append of exists
else
# add node if does not exists
tmp[arr.first] = {'name' => arr.first,'children' => [{'name' => arr.last}]}
end
end
tree = {'name' => 'test','children' => tmp.values}
puts tree
#=> {"name"=>"test", "children"=>[{"name"=>"abc", "children"=>[{"name"=>"123"}]}, {"name"=>"cde", "children"=>[{"name"=>"456"}, {"name"=>"674"}]}]}
puts JSON.generate(tree)
#=> {"name":"test","children":[{"name":"abc","children":[{"name":"123"}]},{"name":"cde","children":[{"name":"456"},{"name":"674"}]}]}
array = [{ name:'Joe', foo:'bar' },
{ name:'Bob', foo:'' },
{ name:'Hal', foo:'baz' }
]
What is an eloquent way to sort so that if foo is empty, then put it at the end, and not change the order of the other elements?
Ruby 1.9.3
array.partition { |h| !h[:foo].empty? }.flatten
array.find_all{|elem| !elem[:foo].empty?} + array.find_all{|elem| elem[:foo].empty?}
returns
[{:name=>"Joe", :foo=>"bar"}, {:name=>"Hal", :foo=>"baz"}, {:name=>"Bob", :foo=>""}]
array = [
{ name:'Joe', foo:'bar' },
{ name:'Bob', foo:'' },
{ name:'Hal', foo:'baz' }
]
arraydup = array.dup
array.delete_if{ |h| h[:foo].empty? }
array += (arraydup - array)
Which results in:
[
[0] {
:name => "Joe",
:foo => "bar"
},
[1] {
:name => "Hal",
:foo => "baz"
},
[2] {
:name => "Bob",
:foo => ""
}
]
With a little refactoring:
array += ((array.dup) - array.delete_if{ |h| h[:foo].empty? })
One can produce keys as tuples, where the first part indicates null/not-null, and the second part is the original index, then sort_by [nulls_last, original_index].
def sort_nulls_last_preserving_original_order array
array.map.with_index.
sort_by { |h,i| [ (h[:foo].empty? ? 1 : 0), i ] }.
map(&:first)
end
Note this avoids all the gross array mutation of some of the other answers and is constructed from pure functional transforms.
array.each_with_index do |item, index|
array << (array.delete_at(index)) if item[:foo].blank?
end
Use whatever you have in place of blank?.