Array inside Hash - Some questions - ruby

I have this code:
a = {}
a["First"] = [true, false]
How can I read "false"? Tried: ["First"][2] but output is blank;
How can I check if ["Second"] exist or if its array length > 0? Tried if a["Second"] is nil end or if a["Second"].value.length>0 but both seems incorrect;
How can I push/pop a new "true" value inside the existing a["First"]'s array?
How can I delete from a the ["First"] index? (such as a.pop["First"])
Can you help me?

Ruby arrays are 0 based so the elements are 0 and 1; there is not 2. Use: a["First"][1]
a["Second"].nil? is true if there is no "Second" element of the hash. Use size to get array length, so: a["Second"].size once you know "Second" exists.
Use: a["First"].push true
Use: a["First"].pop
(a["First"] gets you to the array; a alone is the hash made up of the two arrays.)

combining all comments:
if you want to read false, you should do a["First"][1] not a["First"][2]
a["First"].push('else') to push value
a.delete("First")

Related

How to sort an array in Ruby

Persoane = []
Nume = gets
Persoane.push Nume.split(",")
puts Persoane.sort
I am trying to get an user to input carachters that get split into substrings which get inserted in an array, then the program would output the strings in alphabetical order. It doesnt seem to work and I just get the array's contents, like so:
PS C:\Users\Lenovo\Desktop\Ruby> ruby "c:\Users\Lenovo\Desktop\Ruby\ruby-test.rb"
Scrie numele la persoane
Andrei,Codrin,Bradea
Andrei
Codrin
Bradea
PS C:\Users\Lenovo\Desktop\Ruby>
you can do this :
Nume = gets
puts Nume.split(",").sort
or in 1 line
array = gets.chomp.split(",").sort
The error is because of your use of push. Let's assume that you define the constant Nume by
Nume='Andrei,Codrin,Bradea'
Then, Nume.split(',') would return the Array ['Andrei', 'Codrin', 'Bradea']. When you do a Persoane.push, the whole array is added to your array Persoane as a single element. Therefore, Persoane contains only one Element, as you can verify when you do a
p Persoane
If you sort a one-element array, the result will also be just that one element - there is nothing to sort.
What you can do is using concat instead of push. This would result in Persoane being a 3-element array which can be sorted.
I'm not sure you need use constants here
If you don't need keep user input and use it somewhere, you can just chain methods like this
persons = gets.chomp.split(",").sort
For something a little different, let's not split at all.
people = gets.scan(/[^,]+/).map(&:strip).sort
This will avoid problems like multiple commas in a row yielding empty strings. Of course, you could also avoid that with:
people = gets.split(/\,+/).map(&:strip).sort

What is the real use case for .Any() on arrays?

It clearly seems like I miss something very known and common but I can’t get why empty .Any() invocation on array and list differs in result.
As I know when I call .Any() it’s semantically equals of asking: "Does this box contain any items?". So when I write something like this:
List<int> list= new List<int>();
WriteLine(list.Any());//returns false
list.Add(1);
WriteLine(list.Any());//returns true
It expectedly returns false in the first case because list was empty and true when the item was added.
But further if I’ll try to use array instead and this array will be just initialized but empty (without any items) . Any() call will return true:
int[] arr = new int[2];
WriteLine(arr.Any());//returns true despite in has no items
So what’s the point to call empty .Any() on array to check if it has any items inside if it will always return true? Should I avoid use .Any() for such kind of purpose?
What’s the real use case of empty .Any call on array?
When you create an array, all elements are initialized with default values.
So, int[] arr = new int[2] is actually equal to int[] arr = new int[2] { 0, 0 }. That's why .Any() returns true.
Based on your code example, there is no meaningful use case for Any() method on an initialized array.
But, as I mentioned in the comment to your question, if you are calling a method which returns an array, then you can perform an Any() check on the returned array to determine, if it has got any elements.

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}

Is there an equivalent to `Array::sample` for hashes?

I'm looking to extract n random key-value pairs from a hash.
Hash[original_hash.to_a.sample(n)]
For Ruby 2.1,
original_hash.to_a.sample(n).to_h
I don't know of such method. Still you can do something like:
h[h.keys.sample]
If you need to sample more than one element the code will have to be a bit more complicated.
EDIT: to get key value pairs instead of only the value you can do something like:
keys_sample = h.keys.sample(n)
keys_sample.zip(keys_sample.map{|k| h[k])
Reading the top ranked answers, I'd go with it depends:
If you want to sample only one element from the hash, #Ivaylo Strandjev's solution only relies on hash lookup and Array#sample:
hsh[hsh.keys.sample]
To sample multiple hash elements, #sawa's answer leverages Array#to_h:
hsh.to_a.sample(n).to_h
Note that, as #cadlac mentions, hsh.to_a.sample.to_h won't work as expected. It will raise
TypeError: wrong element type String at 0 (expected array)
because Array#sample in this case returns just the element array, and not the array containing the element array.
A workaround is his solution, providing an n = 1 as an argument:
hsh.to_a.sample(1).to_h
PS: not looking for upvotes, only adding it as an explanation for people newer to Ruby.
If your sample has only one element, you could use this:
sample = h.keys.sample
h.select { |k,v| k == sample }
Or if your sample contains more than one element, use this:
n = 2
sample = h.keys.sample(n)
h.select { |k,v| sample.include?(k) }
One way to accomplish this:
rank_hash = {"Listen" => 1, "Download" => 60, "Share" => 150, "Purchase" => 700 }
rank_array = rank_hash.to_a
Than call this to get random array sample of the k/v pair:
rank_array[rand(0..3)]
or this to not hard-code the arrays length:
rank_array[rand(0..(rank_array.length) -1)]
Example:
["Download", 60]

ruby collect unique elements

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.

Resources