Sort array of hash in ruby - ruby

I have an array of hash like this:
[{683=>5}, {689=>2}, {692=>10}]
I want the result like this:
[{692=>10}, {683=>5}, {689=>2}]
Could any one help me?

Use Enumerable#sort_by. The return value of the block is used as comparison key.
[{683=>5}, {689=>2}, {692=>10}].sort_by { |h| -h.values[0] }
# => [{692=>10}, {683=>5}, {689=>2}]

Related

Convert array of hashes to single hash with values as keys

Given a source array of hashes:
[{:country=>'england', :cost=>12.34}, {:country=>'scotland', :cost=>56.78}]
Is there a neat Ruby one-liner for converting it to a single hash, where the values for the :country key in the original hash (guaranteed to be unique) become keys in the new hash?
{:england=>12.34, :scotland=>56.78}
This should do what you want
countries.each_with_object({}) { |country, h| h[country[:country].to_sym] = country[:cost] }
=> {:england=>12.34, :scotland=>56.78}
You can do that using Enumerable#inject:
countries.inject({}) { |hsh, element| hsh.merge!(element[:country].to_sym => element[:cost]) }
=> {:england=>12.34, :scotland=>56.78}
We initialise the accumulator as {}, and then we iterate over each of the elements of the initial array and add the new formatted element to the accumulator.
One point to add is that using hsh.merge or hsh.merge! would have the same effect for the output, given that inject will set the accumulator hsh as the return value from the block. However, using merge! is better when it comes to memory usage, given that merge will always generate a new Hash, whereas merge! will apply the merge over the same existing Hash.
One more possible solution is:
countries.map(&:values).to_h
=> {"england"=>12.34, "scotland"=>56.78}

How to get the index of a key in a hash?

I'm trying to get the index of a key in a hash.
I know how to do this in an array:
arr = ['Done', 13, 0.4, true]
a = arr.index('Done')
puts a
Is there a method or some sort of way to do this something like this with a key in a hash? Thanks!
Hashes aren't usually treated as ordered structures, they simply have a list of keys and values corresponding to those keys.
It's true that in Ruby hashes are technically ordered, but there's very rarely an actual use case for treating them as such.
If what you want to do is find the key corresponding to a value in a hash, you can simply use the Hash#key method:
hash = { a: 1, b: 2 }
hash.key(1) # => :a
I suppose you could use hash.keys.index(hash.key(1)) to get 0 since it's the first value, but again, I wouldn't advise doing this because it's not typical use of the data structure
There are at least a couple ways you can get this information, the 2 that come to mind are Enumerable's find_index method to pass each element to a block and check for your key:
hash.find_index { |key, _| key == 'Done' }
or you could get all the keys from your hash as an array and then look up the index as you've been doing:
hash.keys.index('Done')

Hash Parsing with Ruby

I have the array of hash as shown below:
#line_statuses = [
{:name=>"1", :status=>"online"},
{:name=>"2", :status=>"online"}
]
I'd like to parse each hash inside of #line_statuses array so that I can print out the name and status as shown below.
1: online
2: online
How would I go about doing this?
Technically your #line_statuses variable is an array, so what you have is an array of hashes. In Ruby, to iterate over an array we use the .each method. Then, in each iteration, we can access the values of the hash using the defined keys:
#line_statuses.each do |hash|
puts hash[:name]
puts hash[:status]
end
So simple...:
#line_statuses.each do |line_status|
puts "#{line_status[:name]}: #{line_status[:status]}"
end
try #line_statuses.each{|i| puts i[:name],i[:status]}
Pretty simple:
#line_statuses.each { |line_status| puts "#{line_status[:name]}: #{line_status[:status]}" }

How to check in Ruby if an array contains other arrays?

I have a multidimensional array like this:
main_array = [ [["a","b","c"],["d","e"]], [["e","f"],["g","h"]] ]
And I would like to check whether main_array contains other arrays.
I've thought that this will work main_array.include?(Array), but i was wrong.
To answer your question directly, I will use #grep method
main_array.grep(Array).empty?
This will ensure that, if your main_array contains at least one element as Array, if returns false.
main_array.grep(Array).size == main_array.size
This will tell you, if all elements are array or not.
You can use the Enumerable#all? if you want to check that the main array contains all arrays.
main_array.all? { |item| item.is_a?(Array) }
or Enumerable#any?
main_array.any? { |item| item.is_a?(Array) }
if you want to check if main_array contains any arrays.
You can use Enumerable#any?:
main_array.any?{|element| element.is_a? Array}
The code you tried (main_array.include?(Array) didn't work because it's checking if the array main_array includes the class Array, e.g. [Array].include?(Array) #=> true).
main_array != main_array.flatten

Ruby - If element in array contains a certain character, return the associated element(s)

Example:
my_array = ['2823BII','4A','76B','10J']
[using magical method delete_if_doesnt_contain()]
my_array.map! do |elements|
elements.delete_if_doesnt_contain('A')
end
I want that to set my_array = ['4A']
Even if I could iterate through an array and just return the index of the element that contains an 'A' I'd be happy. Thanks for any help!
Thanks for the answers below, but one more question.
other_array = ['4']
my_var = other_array.to_s
my_array.select!{|x| x.include?(my_var)}
This isn't working for me. What am I missing? Something happen when I converted the array to a string?
Very easy using #select :
my_array = ['2823BII','4A','76B','10J']
my_array.select { |str| str.include?('A') }
# => ["4A"]
Or if you want to modify the source array, do use the bang version of select :-
my_array.select! { |str| str.include?('A') }
Arup's answer is correct.
However, to answer your last question specifically, "iterate through an array and just return the index of the element that contains an 'A'", the "index" method returns the index for a matching element:
my_array.index {|x| x.include?('A') }
The grep method is a lot shorter
my_array = ['2823BII','4A','76B','10J']
my_array.grep /A/

Resources