Hello to all,

I have a ruby script with a very long hash with more than 300 associations.
The script looks like below:

#!/usr/bin/env ruby

Array_A = []
myHash = {
                "x1" => "2",
                "x2" => "0",
                "x3" => "1",
                .
                .
                .
                "X350" => "1"
                }

myHash.keys.each do |z|
    Array_A << "This is key " + z
end

puts myHash.values.join("|")                            
puts Array_A.join("|") 

But since the hash is very large, for reading purposes I'd like to put the hash at the end of the script and the each.do loop and puts command first,
something like below.

Is there a way to do this?

Thanks in advance for any help.

Array_A = []

myHash.keys.each do |z|
    Array_A << "This is key " + z
end

puts myHash.values.join("|")                            
puts Array_A.join("|") 

myHash = {
                "x1" => "2",
                "x2" => "0",
                "x3" => "1",
                .
                .
                .
                "X350" => "1"
                }

Dani AI

Generated

A concise summary and a few alternative patterns that keep the heavy data out of the flow:

As pointed out, separating processing from data (for example, putting the logic in a method and passing the hash in) is the simplest and clearest fix. The concrete error in this thread was the uppercase name: Ruby treats identifiers that start with an uppercase letter as constants, so saw correct behavior after switching to a lowercase variable name.

If keeping the large literal out of the top of the file is preferred, a few practical approaches that were not shown above:

  • Store the mapping in a separate YAML/JSON file and load it at runtime. This keeps the script short and makes the data easier to edit:
require 'yaml'
data = YAML.load_file(File.expand_path('data.yml', __dir__))
# call processing method with `data`
  • Embed the data after the script using __END__ and parse via the DATA IO (handy for one-file tools):
require 'yaml'
data = YAML.load(DATA.read)
# process(data)

__END__
---
x1: "2"
x2: "0"
  • Put the big hash in a separate Ruby file that defines a constant or returns a hash, then require_relative it from the main script.

Extra notes and troubleshooting pointers: prefer returning newly built arrays from a method rather than mutating globals or constants; that makes the code easier to test and reason about. Moving the text of the hash to a file or DATA helps readability but does not magically reduce memory use unless loading is done lazily or partially. Interpreter warnings (ruby -w) will flag constant-reassignment/name mistakes, and quick p/inspect calls reveal what’s actually being passed into the method.

Recommended Answers

All 8 Replies

Put your code in a method that takes the hash as an argument, then define the hash after the method and call the method at the end.

Hello sepp2k,

Thanks for answer.

I'm a kind of new into Ruby.

How would do the way to do it? I've tried some way but I cannot paste the code for you to see it
since the toolbar Code button is not working.

Thanks again

def my_method(hash)
  # ...
end

hash = {
  "foo" => "bar",
  # ...
}
my_method(hash)

Or even:

def my_method(hash)
  # ...
end

my_method(
  "foo" => "bar",
  # ...
)

Should I to pass as argument the array too?

Is not working yet.

This is what I have so far.

Array_A = []
def load_values(hash={})
    myHash.keys.each do |z|
        Array_A << "This is key " + z
    end
end             

myHash = {
                "x1" => "2",
                "x2" => "0",
                "x3" => "1",
                .
                .
                .
                "X350" => "1"
                }

load_values(myHash)

puts myHash.values.join("|")                            
puts Array_A.join("|")

Thanks again for the help

You're calling your parameter hash, but trying to access it as myHash. I'm also not sure that giving it a default value here is a good idea - it's not clear to me why calling it with an empty hash would ever be desirable - it just wouldn't do anything.

Other than that your code is correct.

Should I to pass as argument the array too?

Assuming you always want to start with an empty array, I'd just create it inside the method (as a non-constant) and then return it as the result.

If you want to be able to start with a non-empty array, passing it as the argument would be a good idea.

Hello sepp2k,

It was a typo about hash and myHash, but is not working yet like this:

Array_A = []
def load_values(myHash)
    myHash.keys.each do |z|
        Array_A << "This is key " + z
    end
end             

myHash = {
                "x1" => "2",
                "x2" => "0",
                "x3" => "1",
                .
                .
                .
                "X350" => "1"
                }

load_values(myHash)

puts myHash.values.join("|")                            
puts Array_A.join("|")

I want to start with an empty array and return the array as result to print the content of Array_A at the end joining it with "|", but I'm not sure how is the correct way to do it inside the method.

What do you mean it does not work. The output I get when running your code (after removing the "..." in the hash of course) is:

2|0|1|1
This is key x1|This is key x2|This is key x3|This is key X350

In what way is that not the output you expected?

Hi sepp2k,

Thank you! it works now. The issue I had it was that I was putting the hash argument with uppercase and it was being detected as constant.

I changed to lowercase and it worked.

Many thanks for your help.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.