ruby collect unique elements - ruby

I have some array of hashes
a = [{name:"x", long:1.0, lat:2.0},
{name:"y", long:2.0, lat:3.0},
{name:"z", long:1.0, lat:2.0}]
how to delete {name:"x", long:1.0, lat:2.0}, which coords are equal of last element, Other words I need to leave last (in my case: with name:"z") hash with unique coords and drop all previous element with same coords

Try using Array#uniq with a block:
a.uniq { |item| [item[:lat], item[:long]] }
The return value of the block is used as the value to compare for uniqueness.
It's not clear why you want "x" to be deleted and not "z", but you could achieve that with the example data set by reversing the array before calling uniq on it.

Related

Get a value from an array of hashes in ruby

I have an array of hashes:
ary = [{1=>"January", 2=>"February", 3=>"March"}, {11=>"Oct", 12=>"Nov", 13=>"Dec"}]
How can I get the value from a particular hash, based on a key? I would like to do something like:
ary[1].select{|h| h[13]}
to get the value "Dec" from the second hash with the key 13. The above statement returns the whole second hash, which is not the requirement:
{11=>"Oct", 12=>"Nov", 13=>"Dec"}
The select statement will return all the hashes with the key 13.
If you already know which hash has the key then the below code will give u the answer.
ary[1][13]
However if you are not sure which of your hashes in the array has the value, then you could do the following:
values = ary.map{|h| h[13]}.compact
Values will have the value of key 13 from all the hashes which has the key 13.
You can merge the two hashes in one and then query the keys of the merged hash.
c = a.merge(b)
=> {1=>"January", 2=>"February", 3=>"March", 11=>"Oct", 12=>"Nov", 13=>"Dec"}
And then you can do something like:
c[1]
=> "January"
Otherwise, if you want to keep the format as an array of different hashes you can just get the value you want this way:
ary[1][12]
=> "Nov"
But that way you have to always know in which hash inside the array is the element you want, which seems a bit confusing because you could just use different hashes instead of an array of hashes and having to remember each hash's position inside the array.
Firstly make a single hash and then return the value of hash by key.
Make single hash from array with merging elements.
Method 1
hash = ary.reduce({}, :merge)
Method 2
hash = ary.inject(:merge)
Then return the value by key.
hash[13]

How to check if nested hash attributes are empty

I have a Hash
person_params = {"firstname"=>"",
"lastname"=>"tom123",
"addresses_attributes"=>
{"0"=>
{"address_type"=>"main",
"catalog_delivery"=>"0",
"street"=>"tomstr",
"city"=>"tomcity"
}
}
}
With person_params[:addresses_attributes], I get:
# => {"0"=>{"address_type"=>"main", "catalog_delivery"=>"0", "street"=>"tomstr", "zip"=>"", "lockbox"=>"", "city"=>"tomcity", "country"=>""}}
1) How can I get a new hash without the leading 0?
desired_hash = {"address_type"=>"main", "catalog_delivery"=>"0", "street"=>"tomstr", "zip"=>"", "lockbox"=>"", "city"=>"tomcity", "country"=>""}
2) How can I check whether the attributes in the new hash are empty?
Answer 1:
person_params[:addresses_attributes]['0']
Answer 2:
hash = person_params[:addresses_attributes]['0']
hash.empty?
This looks just like a params hash from Rails =D. Anyway, it seems that your addresses_attributes contains some nested attributes. This means that what you have in practice is more of an array of hashes than a single hash, and that's what you see right? Instead of it being an actually Ruby Array, it is a hash with the index as a string.
So how do you get the address attributes? Well if you only want to get the first address, here are some ways to do that:
person_params[:addresses_attributes].values.first
# OR
person_params[:addresses_attributes]["0"]
In the first case, we will just take the values from the addreses_attributes hash, which gives us an Array from which we can take the first item. If there are no values in addresses_attributes, then we will get nil.
In the second case, we will just ask for the hash value with the key "0". If there are no values in addresses_attributes, we will get nil with this method also. (You might want to avoid using the second case, if you are not confident that the addresses_attributes hash will always be indexed from "0" and incremented by "1")

Why am I geting wrong results in my array with I iterate?

I am iterating on a array within a Object van. I am trying to pop the elements of the array into another object array. See below.
#van.bikes.each { #garage<<( #van.removebike )}
def removebike
#bikes.pop
end
When I do this the resulting array in the garage has missing elements and/or duplicate elements.
The reason for this is that when ruby iterates on the array it sets number of iterations based on the original array size. When you pop an element from that array the size changes so the iteration can not work properly.
You can use instead,
#van.bikes.count.times { #garage<<( #van.removebike )}
You can try this too..
#garage = []
#van.bikes.each{|bike| #garage << bike}

Avoid recalculating some values with Enumerable methods

Some methods on Enumerable such as max_by, min_by, or find evaluate some related value for the items iterated, and give back one of the original items. I often want not the original value but the evaluated form. In this example:
max = some_enumerable_object.max_by{|e| some_function(e)}
some_function(max)
max_by selects an item max, but I want the value some_function(max) rather than the max itself. Doing some_function(max) seems waste of calculation because it was already evaluated within the iteration. Is there a way to access some_function(max) without recalculation?
You can call map then max:
max_value = some_enumerable_object.map { |e| some_function(e) }.max
You can always use map to create a sub-array containing your original value, along with your computed value:
max = some_enumerable_object.map{ |o|
[o, some_function(o)]
}.max_by{ |o,e| e }
Once you're done, you can grab your original value, or the result of the function in your max variable.

Having a hard time understanding & implementing some Ruby code

myitem.inject({}) {|a,b| a[b.one] = b.two; a}
Where:
myitem is a class which holds an array or pair objects (pair objects have two fields in them one and two)
I am not sure what the above code is supposed to do?
Starting with an empty map, set its value for the b.one key to b.two.
In other words, for every item in the "myitem" collection, create a map entry. The key will be an item's "one" value. That map entry's value will be the item's "two" value.
The block given to "inject" receives two parameters. The first is the "accumulator". It's initial value in this case is the empty map passed to "inject". The second parameter is the current item in the collection. In this case, each item in the collection.
The block must return whatever will be used as the next accumulator value, in this case, the map. We want to keep using the same map, so when we're done, the "inject" method will return the map with all the key/value pairs.
Without saving the results of the inject it's a bit worthless.
It's a pedantic way of writing
h = {}
myitem.each { |b| h[b.one] = b.two }
or to be closer to your original code
a = {}
mytem.each { |b| a[b.one] = b.two }
(I personnaly hate this pattern (and people who use it) as it needs the ; a at the end, losing all the functional aspect of inject. (Using a side-effect function inside a 'functional pattern', and then realizing that the later function (a[..]) doesn't return the expecting object is just wrong, IMO).
Inject is normal use to 'fold' a list into a result like
[1,2,3].inject(0) { |sum, x| sum+x }
=> 6 # (0+1+2+3)
here sum is the result of the last call to the block, x is each value on the list and 0 is the initial value of sum.
[2,3].inject(10) { |p,x| p*x }
=> 60 # 10*2*3
etc ...
Hash[my_item.map {|object| [object.one, object.two]}]
is another way to do it.

Resources