Array to hash of arrays - ruby

I have an array of values I got from a table:
arr = ["One", "0", "31.948", "0", "6.94",
"Two", "0", "31.948", "0", "6.94",
"Three", "0", "23.961", "0", "5.21"]
I need to get a hash of arrays:
hash = {
"One" => ["0", "31.948", "0", "6.94"],
"Two" => ["0", "31.948", "0", "6.94"],
"Three" => ["0", "23.961", "0", "5.21"]
}
How do I do it?

Assuming you want an array for each value, this will do it.
Hash[arr.each_slice(5).map{|k, *v| [k, v]}]

Related

Ruby - keys of one hash into values of another hash

I have to hashes like so:
hash1 = {
"a" => 1,
"b" => 1,
"c" => 1,
"d" => 1
}
hash2 = {
"1" => 1,
"2" => 1,
"3" => 1,
"4" => 1
}
And I need to merge them so I end up with this:
hash1 = {
"a" => "1",
"b" => "2",
"c" => "3",
"d" => "4"
}
But I don't know where to begin. Help appreciated.
You can try the following:
Hash[hash1.keys.zip(hash2.keys)]
At first, you get array of keys for each hash with hash1.keys and hash2.keys:
["a", "b", "c", "d"]
["1", "2", "3", "4"]
Secondly, you create an array of arrays with hash1.keys.zip(hash2.keys):
[["a", "1"], ["b", "2"], ["c", "3"], ["d", "4"]]
Then with Hash[<...>] you create a Hash where the first value from the first inner array goes as key and the second as value:
{"a"=>"1", "b"=>"2", "c"=>"3", "d"=>"4"}
Example

Produce all permutations of a number's digits

I've recently solved a problem, which takes a 3-4 digit number, such as 1234, (as well as some greater numbers) and returns a sorted array of ALL the possible permutations of the numbers [1234, 1432, 4213, 2431, 3412, 3214, etc.]
I don't like my solution, because it used .times to add the numbers to the array, and thus is still fallible, and furthermore ugly. Is there a way that the numbers could be added to the array the perfect number of times, so that as soon as all the possible shufflings of the numbers have been reached, the program will stop and return the array?
def number_shuffle(number)
array = []
number = number.to_s.split(//)
1000.times{ array << number.shuffle.join.to_i}
array.uniq.sort
end
Do as below using Array#permutation:
>> a = 1234.to_s.chars
=> ["1", "2", "3", "4"]
>> a.permutation(4).to_a
=> [["1", "2", "3", "4"],
["1", "2", "4", "3"],
["1", "3", "2", "4"],
["1", "3", "4", "2"],
["1", "4", "2", "3"],
["1", "4", "3", "2"],
["2", "1", "3", "4"],
["2", "1", "4", "3"],...]
Your modified method will be :
def number_shuffle(number,size)
number.to_s.chars.permutation(size).to_a
end
For your method it will be:
def number_shuffle(number)
a = number.to_s.chars
a.permutation(a.size).to_a.map { |b| b.join.to_i }
end
p number_shuffle 123 # => [123, 132, 213, 231, 312, 321]

Make two dimensional array

My array is ["Mehmet,1,3,0,0,0\n", "Veli,2,1,2,0,2\n", "Ali,0,1,1,0,0\n"].
I want to declare two dimensional array like array[1][2] with first dimension for name and second one for note.
How can I make it?
Text.txt is
Mehmet,1,3,0,0,0
Veli,2,1,2,0,2
Ali,0,1,1,0,0
My code is
filename = "text.txt"
results = []
File.new(filename, "r").each { |line| results << line }
results.inject([]){|ar,s|
ar.concat(s.split(/,/))}
puts results.inspect
To modify the set that you first posted:
data = ["Mehmet,1,3,0,0,0\n", "Veli,2,1,2,0,2\n", "Ali,0,1,1,0,0\n"]
data = data.map {|x| y = x.split(","); [y.delete_at(0), y] }
=> [["Mehmet", ["1", "3", "0", "0", "0\n"]],
["Veli", ["2", "1", "2", "0", "2\n"]],
["Ali", ["0", "1", "1", "0", "0\n"]]]
puts data[0][0]
=> Mehmet
array = File.read("text.txt").split
# => ["Mehmet,1,3,0,0,0", "Veli,2,1,2,0,2", "Ali,0,1,1,0,0"]
array.map { |ar| x, *xs = ar.split(","); [x, xs.join] }
# => [["Mehmet", "13000"], ["Veli", "21202"], ["Ali", "01100"]]
Or, if you don't want to join the second sub-array
array.map { |ar| x, *xs = ar.split(","); [x, xs] }
# => [["Mehmet", ["1", "3", "0", "0", "0"]],
# ["Veli", ["2", "1", "2", "0", "2"]],
# ["Ali", ["0", "1", "1", "0", "0"]]]
2d array means array of arrays. So, simply it can be like:
board = [ [ 1, 2, 3 ],[ 4, 5, 6 ]]
Are you looking for something like this?
array = ["Mehmet,1,3,0,0,0\n", "Veli,2,1,2,0,2\n", "Ali,0,1,1,0,0\n"]
new_array = array.map do |elem|
splited = elem.split(/[,\s]/)
[splited.shift, splited]
end
# => [["Mehmet", ["1", "3", "0", "0", "0"]],
# ["Veli", ["2", "1", "2", "0", "2"]],
# ["Ali", ["0", "1", "1", "0", "0"]]]

How to combination/permutation in ruby?

I've this familiar question that looks like permutation/combination of the Math world.
How can I achieve the following via ruby?
badges = "1-2-3"
badge_cascade = []
badges.split("-").each do |b|
badge_cascade << b
end
Gives: => ["1", "2", "3"]
But I want it to be is:
=> ["1", "2", "3",
"1-2", "2-3", "3-1", "2-1", "3-2", "1-3",
"1-2-3", "2-3-1", "3-1-2"]
Functional approach:
bs = "1-2-3".split("-")
strings = 1.upto(bs.size).flat_map do |n|
bs.permutation(n).map { |vs| vs.join("-") }
end
#=> ["1", "2", "3", "1-2", "1-3", "2-1", "2-3", "3-1", "3-2", "1-2-3", "1-3-2", "2-1-3", "2-3-1", "3-1-2", "3-2-1"]
You ned to use Array#permutation method in order to get all permutations:
arr = "1-2-3".split '-' # => ["1", "2", "3"]
res = (1..arr.length).reduce([]) { |res, length|
res += arr.permutation(length).to_a
}.map {|arr| arr.join('-')}
puts res.inspect
# => ["1", "2", "3", "1-2", "1-3", "2-1", "2-3", "3-1", "3-2", "1-2-3", "1-3-2", "2-1-3", "2-3-1", "3-1-2", "3-2-1"]
Let me explain the code:
You split string into array passing separator '-' to String#split method
You need all permutations of length 1, 2, 3. Range 1..arr.length represents all these lengths.
You collect an array of all permutations using Enumerable#reduce.
You will get array of arrays here:
[["1"], ["2"], ["3"], ["1", "2"], ["1", "3"], ["2", "1"], ["2", "3"], ["3", "1"], ["3", "2"], ["1", "2", "3"], ["1", "3", "2"], ["2", "1", "3"], ["2", "3", "1"], ["3", "1", "2"], ["3", "2", "1"]]
You transform all subarrays of this array into strings using Array#join with your '-' separator inside of Enumerable#map
Array#permutation(n) will give you all the permutations of length n as an Array of Arrays so you can call this with each length between 1 and the number of digits in badges. The final step is to map these all back into strings delimited with -.
badges = "1-2-3"
badges_split = badges.split('-')
permutations = []
(1..badges_split.size).each do |n|
permutations += badges_split.permutation(n).to_a
end
result = permutations.map { |permutation| permutation.join('-') }
Update: I think Alex's use of reduce is a more elegant approach but I'll leave this answer here for now in case it is useful.

How do I quickly reorder a Ruby Array given an order?

I have an array of values, and an array which determines the order.
How can I quickly re-arrange the array in the given order?
data = ['0','1','2','3','4','5']
order = [3,1,2,0,4,5]
I want:
data = ['3','1','2','0','4','5']
You can use the values_at method written for this kind of task:
data = ['0','1','2','3','4','5']
order = [3,1,2,0,4,5]
data.values_at *order
# => ["3", "1", "2", "0", "4", "5"]
data = ["0", "1", "2", "3", "4", "5"]
order = [3, 1, 2, 0, 4, 5]
> order.map{|x| data[x]}
=> ["3", "1", "2", "0", "4", "5"]
If you are not sure if the indices are correct, you can do this:
> order.map{|x| data.fetch(x)} # will raise an exception if index out of bounds
=> ["3", "1", "2", "0", "4", "5"]
Not as good as #Jakub's answer using Array#values_at (which I would argue should be the accepted answer) but here are some other fun alternatives:
p data.sort_by.with_index{ |d,i| order[i] }
p data.zip(order).sort_by(&:last).map(&:first)

Resources