I have the following array.
[
{"title"=>"un", "link"=>nil, "description"=>""},
{"title"=>"deux", "link"=>"https://apple.com", "description"=>"Products"},
{"title"=>"three", "link"=>"http://www.amazon.com", "description"=>"Welcome"},
{"title"=>"four", "link"=>"https://apple.com", "description"=>"iPad"},
]
I'd like to remove hashes whose link is nil or empty, an return an array of links to get:
["https://apple.com", "http://amazon"]
Not sure how to remove hashes and get unique links only.
To remove both empty ("") and nil values:
arr.map { |a| a["link"] }.reject(&:blank?).uniq
As #Arup pointed out blank is in Rails, pure Ruby solution would be:
arr.map { |a| a["link"] }.reject{|e| e == "" || e == nil}.uniq
Please try like below code
arr.map {|o| o['link'] }.reject { |e| e.to_s.empty? }.uniq
Solution:
a = [
{"title"=>"un", "link"=>nil, "description"=>""},
{"title"=>"deux", "link"=>"https://apple.com", "description"=>"Products"},
{"title"=>"three", "link"=>"http://www.amazon.com", "description"=>"Welcome"},
{"title"=>"four", "link"=>"https://apple.com", "description"=>"iPad"},
]
a.map{|data| data["link"] }.reject(&:blank?).uniq
Explanation:
a is the array of hashes
Map will go through each hash in the array and create a new array with just the "link" value. If the original hash didn't have a link key it will create a nil value in the new array.
Example result after map:
[nil, "https://apple.com", "https://www.amazon.com", "https://apple.com"]
Reject then calls the rails active support method blank? on each item in the array and if blank? returns true returns a new array without the value:
[nil.blank?, "https://apple.com".blank?, "https://www.amazon.com".blank?, "https://apple.com".blank?]
Result:
["https://apple.com", "https://www.amazon.com", "https://apple.com"]
Uniq then generates an array without duplicates (an alternative is to use a ruby set)
["https://apple.com", "https://www.amazon.com"]
You could do by:
arr.map {|o| o['link'] }.compact.uniq
compact remove all nils, and uniq returns the unique values.
You could go with Enumerable#each_with_object :
array.each_with_object([]) do |h, a|
a << h['link'] unless h['link'].nil? || h['link'].empty?
end.uniq
# => ["https://apple.com", "http://www.amazon.com"]
Related
I have a hash of an array of arrays. The array is indexed by the hash (that is the way I am reading this):
[
{"name":"G18","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]},
{"name":"G19","data": [["M16",141],["M203",57],["M29S",142]]},
{"name":"G20","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]}
]
I want to select the hashes that contain the array G18, and return only the data.
I tried searching for answer, but I haven't found anything like this yet.
This will work for you if you have only one item with name "G18":
a.find {|e| e[:name] == "G18" }[:data]
See: Enumerable#find in the official docs.
Given:
ary = [
{"name":"G18","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]},
{"name":"G19","data": [["M16",141],["M203",57],["M29S",142]]},
{"name":"G20","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]}
]
Try:
ary.select{|hsh| hsh[:name] == 'G18'}.first[:data]
=> [["X301", 141], ["x7901", 57], ["x2100", 142], ["x90", 58]]
In fact, marmeladze's answer is the correct one:
ary.find{|hsh| hsh[:name] == 'G18'}[:data]
Using select was a misfire.
collection = [
{"name":"G18","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]},
{"name":"G19","data": [["M16",141],["M203",57],["M29S",142]]},
{"name":"G20","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]}
]
def data_for_name(name, collection)
collection.find { |item| item[:name] == name }[:data]
end
p data_for_name("G18", collection)
I have a array of hashes like :
arry = {hash1, hash2, hash3,hash4 ....hash_N}
for each hash,
hash1 ={ "deviceId"=>"868403021230682", "osVersion"=>"6.0", "deviceOS"=>"Android",
"appVersion"=>"1.7.2", "action"=>"Enter"}
hash2 = { "deviceId"=>"868403021230682", "osVersion"=>"6.0", "deviceOS"=>"Android",
"appVersion"=>"1.7.2", "action"=>"Leave"}
because it is possible that for each hash "action"=>"Enter" or "Leave" will not always appear as a pair , for example, action for hash3, hash4,hash5 could be all "Enter" . My idea is only consider two hashes who can make a pair like hash1 and hash2, remove other from array or put them into other array.
so the new array should just contain [hash1, hash2, hash7,hash8] , lets say hash7 and 8 are also a pair.
should I use each_with_index? my code is like this:
def get_result(doc)
result = []
doc.each_slice(2).map { |pair|
pair.each_with_index { |element, index|
if ( pair[index].has_value?([:action] => "enter") &&pair[index+1].has_value?([:action] => "Leave")
result.push(pair)
end
}
}
end
but the if statement is not working right , kind of confused about how to use each_with_index hope someone can help me out
Based on the way your method is created , you can do it this way:
def get_result(doc)
doc.each_slice(2).to_a.map{ |ah| ah if ah[0][:action] == 'Enter' && ah[1][:action] == 'Leave'}.compact.flatten
end
Explanation
The variable doc is an array of hashes [hash1, hash2, ...] when we create doc.each_slice(2).to_a will return an array of pair of hashes [[hash1, hash2],[hash3,hash4]...], Now when we do map and get the pair of hashes that has actions per order ('Enter','Leave') we get an array with nil values like this [[hash1,hash2],nil,[hash5,hash6]..] . we use compact to remove the nil values. now the array is like this [[hash1,hash2],[hash5,hash6]..] (array of pair of hashes) and the result expected is an array of hashes, that's why we need flatten, it will remove the inside array and return an array like this [hash1, hash2, hash5, hash6 ...]
If you need to get the list of deleted hashes, i think it would be better if add another method to do it. Otherwise, you can make the get_result method return two arrays.
Here is how you can do it :
def get_result(doc)
removed_elms = []
result = doc.each_slice(2).to_a.map do |ah|
# if you just need them different (not the first one 'Enter' and the second one 'Leave') you need to set the commented condition
# if ['Enter','Leave'].include?(ah[0][:action] && ah[1][:action]) && ah[0][:action] != ah[1][:action]
if ah[0][:action] == 'Enter' && ah[1][:action] == 'Leave'
ah
else
removed_elms << ah
nil
end
end.compact
[result.flatten, removed_elms.flatten]
end
I have a hash hash like so:
hash = {"Addaptive Accessibility"=>["one","two"],
"Atmosphere (Feeling/Safety)"=>["three", "four"],
"Aquatics (Size)"=>["five", "six"]}
I then have an array array:
array = ["one","seven"]
I need to search the hash for each word in my array, and if the word is found I need to return the associated key from the hash. Something like this:
array.each do |word|
if hash.include? word
puts key
end
end
How can I write that, and write it better?
To answer your original question, I'll throw in another solution which I think is the easiest one to understand:
hash.find{|k,v| v.include? word }.first
This will only iterate until a match is found, i.e. you will probably save a few cycles. As opposed to #ArupRakshit's solution, this will however only find the first match.
I must however stress that you are indeed using the hash in the wrong direction – just flip keys and values around!
How is this ?
hash.select{ |_,v| v.any?{|e| array.include? e } }.keys
# => ["Addaptive Accessibility"]
hash.select{ |_,v| v.any?(&array.method(:include?)) }.keys
# => ["Addaptive Accessibility"]
hash.keys.select {|k| !(array & hash[k]).empty?}
array & hash[k] is an array composed of the elements common to both array and hash[k].
we are only concerned with whether this 'intersection' is empty ([]).
we could have used (array & hash[k]).any?, which is simpler, provided you never have keys false or nil, since [nil, false].any? => false.
I have an array of arrays and I would like to remove all the items that have elements which are nil or empty after stripping spaces. Look at this snippet:
x = Array.new
x << ["A","B", " ", "D"]
x << [""," ", nil, ""]
x << ["E","Q", "F", "M"]
I would like to remove the second record because, it contains no real data.
What would be the best way to do this? Should I simply iterate over the array and and write if-else conditions to test?
If using plain Ruby, you can do
x.reject{ |arr| arr.all? {|elem| elem.nil? || elem.strip.empty? }}
If using rails, thanks to the helper methods you can do
x.reject{ |arr| arr.all?(&:blank?) }
The key methods are reject and blank?
x.reject { |a| a.join.strip.length == 0 }
If first array will contain nil, when Chubas variant don't work.
Lets slightly modify it:
(using rails)
x.compact.reject{ |arr| arr.all?(&:blank?) }
I have the following:
array_of_hashes = [{:a=>10, :b=>20}, {:a=>11, :b=>21}, {:a=>13, :b=>23}]
How would I go about finding if :a=>11 exists in array_of_hashes
array_of_hashes.include? does not seem to work
array_of_hashes.any? {|h| h[:a] == 11}
You did ask for a boolean result in the OQ, but if you really want the hash element itself do:
array_of_hashes.detect { |h| h[:a] == 11 }
If you want the result really fast you could group the original object and then get the result with a single hash lookup:
t = array_of_hashes.group_by { |x| x[:a] }
t[11]