Ruby : Extract Key and Value from hash
I'd say that the most elegant way to go about this is probably to convert data
into a Hash first (assuming there are never any duplicate keys), like so:
data = data.map { |x| [x['key'], x['value']] }.to_h
# => {"Name"=>"Jason", "Age"=>"21", "last_name"=>"bourne"}
The #to_h
method expects each element of the array to be an array in the form [key, value]
, so the #map
call processes each element of data
to convert it into that form.
Once this has been done, you can simply access keys like any other hash:
data['Name'] # => "Jason"
data['Age'] # => "21"
How to extract value from hash in Rails
@value_hash
is not a hash
, it's an ActiveRecord::Relation
(as the error states).
In your example, @value_hash
has only one member. To get that member, which is an instance of the class CustomValue
(which is still not a hash
!), you can do:
custom_value = @value_hash.first
Then, to get the year, you can do:
custom_value.year
Or, you could do it in one shot as:
@value_hash.first.year
Which is just a long way of saying exactly what Sachin R said (so you should accept their answer).
How to extract values from hashes into separate arrays?
A simple solution is to iterate the array of hashes and add the required values to two separate arrays:
months = []
counts = []
array_of_hash.each do |hash|
months << hash["month"]
counts << hash["count"]
end
But you could also use each_with_object
months, count = array_of_hash.each_with_object([[], []]) do |hash, accu|
accu[0] << hash["month"]
accu[1] << hash["count"]
end
or iterate twice and get the months and counts separately:
months = array_of_hash.map { |hash| hash["month"] }
counts = array_of_hash.map { |hash| hash["count"] }
How to extract a value from a hash
The keys
method returns an array of the key names; it doesn't return the values.
Given these inputs:
json = '{"user1":{"about_you":"jjhj","age":18,"email":18},"user2":{"about_you":"jjhj","age":18,"email":18},"user3":{"about_you":"jjhj","age":18,"email":18}}'
data_hash = JSON.parse(json)
Try just iterating over the hash's keys and values:
data_hash.each { |k,v| puts v['email'] }
Or if you prefer:
data_hash.each do |k,v|
puts v['email']
end
Each returns:
18
18
18
Extract values from Ruby data hash and concatenate values into single continuous String
As your input (h
) is a hash that can contain hashes in its values, you can implement the method to extract the strings from the values using recursion:
input = {a: "da", b: {c:"test", e: {f: "bird"}}, d:"duck"}
def extract_values_from_hash(input)
return input unless input.is_a?(Hash)
input.flat_map { |_, v| extract_values_from_hash(v) }
end
extract_values_from_hash(input).join
# datestbirdduck
What it does is to receive the hash (input
) from which extract the values adding a guard clause - as the base case, which returns the argument the method was called with if it's a hash object, otherwise it flattens and map the object invoking the method itself. This way you extract every value from the initial method argument.
Notice this extracts anything that's in the input that's not directly a hash, if you happen to have an object like this:
{a: "da", b: {c:"test", e: {f: "bird"}}, d:"duck", g: 1, h: [{i: "hola"}, {j: "chao"}]}
The result would be:
"datestbirdduck1{:i=>\"hola\"}{:j=>\"chao\"}"
Extract the hash value substring from each line in a TextBox
I've done quite a bit of work to reduce your code down to the bare essentials of computing your hashes without relying on the UI. I've then got the code that requires the UI separated out so that it has nothing to do with computing hashes.
To start with I created a single hashing function that you can use to compute any hash.
public Task<string> ComputeHash(string file, Func<HashAlgorithm> create)
{
return Task.Run(() =>
{
using (var crypto = create())
{
using (var stream = File.OpenRead(file))
{
return String.Concat(
crypto.ComputeHash(stream).Select(x => x.ToString("X2")));
}
}
});
}
I've now created two fields to store the list of files and the resulting hashes.
private string[] _fileNames = null;
private string[] _hashes = null;
I'll show the code that sets the _fileNames
array later, but for now this is the code that you can call to compute your hashes:
private async Task<String> Run(bool md5, bool sha1, bool sha256, bool sha512)
{
File.Delete(Path.Combine(Environment.CurrentDirectory, "log.txt"));
Func<HashAlgorithm> hashAlgorithm = null;
if (md5) hashAlgorithm = () => MD5.Create();
else if (sha1) hashAlgorithm = () => SHA1.Create();
else if (sha256) hashAlgorithm = () => SHA256.Create();
else if (sha512) hashAlgorithm = () => SHA512.Create();
if (hashAlgorithm == null)
{
return "No hash algorithm selected.";
}
else if (_fileNames == null || _fileNames.Length == 0)
{
return "No file selected." + "\n";
}
else if (_fileNames.Any(f => !File.Exists(f)))
{
return "Invalid filename." + "\n";
}
else
{
var tasks = _fileNames.Select(f => ComputeHash(f, hashAlgorithm)).ToArray();
_hashes = await Task.WhenAll(tasks);
return "Success";
}
}
The hardest part of this code, in my opinion, is the use of Func<HashAlgorithm> hashAlgorithm
to store the hashing algorithm. If you're not familiar with a Func<>
then it's worth looking up, but think of it as a way to store a function in a variable so that you can call the function later.
Now, finally, we have the two bits of code that interact with the UI:
private void filePickerButton_Click(object sender, RoutedEventArgs e)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.InitialDirectory = "C:\\Users";
dialog.IsFolderPicker = false;
dialog.Multiselect = true;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
{
_fileNames = dialog.FileNames.ToArray();
filePicketTextBox.Text = string.Join("\n", dialog.FileNames);
}
else
{
outputTextBox.Text = "Operation cancelled." + "\n";
}
}
private async void runButton_Click(object sender, RoutedEventArgs e)
{
string result = await Run(
md5CheckBox.IsChecked,
sha1CheckBox.IsChecked,
sha256CheckBox.IsChecked,
sha512CheckBox.IsChecked);
outputTextBox.Text = result;
}
The end result is that you have two arrays, _fileNames
& _hashes
that you can use to get the hash for each file name. No need for splitting text.
Extracting values from a hash
Try the following:
#!/usr/bin/env ruby
require 'httparty'
(HOST, ID, VERSION) = ARGV
class MyApi
include HTTParty
format :json
end
response = MyApi.get("http://#{HOST}/v1/dc/manifest/#{ID}/#{VERSION}")
puts response.inspect
The addition of the format :json
tells HTTParty to parse the response as JSON. Then you'll get a hash you can iterate over properly.
Extracting value from nested hashes and arrays in Ruby
Short alternative way using Array#transpose
method:
> h.values.flatten(1).transpose.last
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
# with to number conversion
> h.values.flatten(1).transpose.last.map(&:to_i)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Benchmarks
require 'benchmark'
h = {
a: [ ["c", "1"],["d","2"],["e","3"],["f","4"] ],
b: [ ["g","5"],["h","6"],["i","7"],["j","8"] ],
c: [ ["k","9"],["l","10"],["m","11"],["n","12"] ]
}
Benchmark.bm(10) do |x|
x.report("transpose") do
1000.times { h.values.flatten(1).transpose.last.map(&:to_i) }
end
x.report("collect/map") do
1000.times { h.values.flatten(1).collect(&:last).map(&:to_i) }
end
x.report("regexp") do
1000.times { h.values.flatten.select { |v| v.match(/\d/) }.map(&:to_i) }
end
x.report("Integer") do
1000.times { h.values.flat_map { |a| a.map { |_,e| Integer(e) } } }
end
end
Results
user system total real
transpose 0.000000 0.000000 0.000000 ( 0.006971)
collect/map 0.010000 0.000000 0.010000 ( 0.007490)
regexp 0.030000 0.010000 0.040000 ( 0.031939)
Integer 0.010000 0.000000 0.010000 ( 0.006832)
Related Topics
How to Dynamically Call a Math Operator in Ruby
Ruby Basic Data Type Conversion
What Is the "Right" Way to Iterate Through an Array in Ruby
Ruby: How to Turn a Hash into Http Parameters
How to Fix "Your Ruby Version Is 2.3.0, But Your Gemfile Specified 2.2.5" While Server Starting
Nested Models and Parent Validation
Dynamic Class Definition with a Class Name
Rails 3. Creating a Production Database
How to Serve Static Files via Rack
Differencebetween Raising Exceptions VS Throwing Exceptions in Ruby
Best Way to Add Comments in Erb
Best Ruby on Rails Social Networking Framework
What Is Java Interface Equivalent in Ruby
What Are Some Good Ruby-Based Web Crawlers
Is There a Better Way of Checking Nil or Length == 0 of a String in Ruby
Rails: an Elegant Way to Display a Message When There Are No Elements in Database
Getting "Warning! Path Is Not Properly Set Up" When Doing Rvm Use 2.0.0 --Default