Pull data from array into new array - ruby

I have the following code. Legislators is an array of data.
testArray = Legislators.each { |legislator| legislator['name']['first']}
In powershell this would leave me with an array of the legislator's first names.
Do I need to add each legislator object to the testArray as I loop through? I feel like there's probably a shortcut...

Try
testArray = Legislators.map { |legislator| legislator['name']['first'] }
each only iterates over legislators and executes the block; map iterates over it and returns an array whose elements are the values of the block.

Related

How to add object attributes in array from another array in Ruby

Firstly I have an array of multiple objects [#<Vgpop::Game:0x00007fcd5b246a00 #name="Super Smash Bros. Ultimate", #console=nil, #score=nil>....]
Then I have an array of my consoles that looks like this: ["Nintendo Switch"...]
How do I map the values from my second array to my object array so that the return is:
[#<Vgpop::Game:0x00007fcd5b246a00 #name="Super Smash Bros. Ultimate", #console="Nintendo Switch", #score=nil>....]
Seems like we can come up with this solution my friend:
first_array.each_with_index { |vgpop, i| vgpop.name = second_array[i] }

Accessing specific attribute of an object

Hello I have the following object
object = [#<ShopifyAPI::DiscountCode:0x000000000e1c78a8 #attributes={"code"=>"Disc2", "amount"=>"1.00", "type"=>"percentage"}, #prefix_options={}, #persisted=true>]
How can I properly access the "code" name of that object?
I have tried object[:code] and object.code but it appears I am overlooking something.
object is an array of ShopifyAPI::DiscountCode.
The best way to access it is
object[0].attributes['code']
If u want code of all the objects available in the array, you could get the array of values by
object.map { |obj| obj.attributes['code'] }
Given that this is an Array of ShopifyAPI::DiscountCodes (which inherit from ActiveResource::Base)
You can call the code method on them. eg:
object[0].code
#=> "Disc2"
object.map(&:code)
#=> ["Disc2"]
First, object is array:
obj0 = object[0]
Second, this is instance variable:
attributes = obj0.instance_variable_get(:#attributes)
Last, gets values by keys:
attributes['code']

Access variable hash depth values with square brackets notation

Given this hash:
hash1= { node1: { node2: { node3: { node4: { node5: 1 } } } } }
We access inside nodes with square brackets like this:
hash1[:node1][:node2][:node3][:node4]
Now I have a hash that I know will always be nested as it is an XML response from a SOAP webservice, but neither the depth of the hash nor the names of the nodes stay the same. So it would be nice if I could ask the user of my application for the hash depth and store it in a variable. And then be able to do hash1[:hash_depth] and achieve the same result as above.
I have accomplished what I want by the following code:
str = 'node1,node2,node3,node4'
str_a = str.split(',')
hash_copy = hash1
str_a.each { |s| hash_copy = hash_copy.[](s.to_sym) }
hash_copy
=> {:node5=>1}
hash1[:node1][:node2][:node3][:node4]
=> {:node5=>1}
that is asking the user to enter the hash depth separated by commas, store it in a string, split it, make an array, clone the original hash, go down each level and modify the hash till I get to the desired node. Is there a way to do it with the square brackets notation and using a variable to store the depth without modifying the hash or needing to clone it?
Edit:
someone answered with the following (can't see his post anymore???)
hash_depth="[:node1][:node2][:node3][:node4]"
eval "hash1#{hash_depth}"
Although eval does everything you need, there is another approach, since you already have the working code for comma-separated list:
hash_depth="[:node1][:node2][:node3][:node4]"
csh = hash_depth.gsub(/\A\[:|\]\[:|\]\Z/, { '][:' => ',' })
#⇒ "node1,node2,node3,node4"
And now you are free to apply your existing function to csh.
If this is a webapp, I think you should prepare a list of short textareas, which starts with a single text item, and the user can keep adding a new item to the list by clicking on a button. The areas will be filled by the user, and will be sent.
Then, you will probably receive this through some serialized form. You decode this to get an array of strings:
str_a = ["node1", "node2", "node3", "node4"]
and you can reach the inner element by doing:
str_a.inject(hash1){|h, s| h[s.to_sym]} #=> {:node5 => 1}

algorithm for regrouping data from flat file to hash with keys

I run into this fairly frequently. I have a batch of data (stored in CSV, XML, it doesn't matter) in some version of this format:
key1|value1
key1|value2
key1|value3
key2|value4
key2|value5
etc.
and need to be able to handle it in this form:
data[key1] => [value1, value2, value3]
data[key2] => [value4, value5]
etc.
What's the best approach to converting from A to B? I typically loop over the list like this (pseudocode), but I don't like that I have to repeat my array building code.
data = []
values = []
currentKey = ""
foreach (line in inputData) {
key, value = split(line)
if ((currentKey != "") and (currentKey != key)) {
data[currentKey] = values
values = []
}
currentKey = key
values.add(value)
}
// this is the part I don't like, but it's necessary to capture the last group
data[currentKey] = values
I'm specifically not naming a language, since I've had to do this in at least Javascript, C#, Perl, and PHP. If there are language-specific solutions that would be great, but I'm really looking for the most efficient general algorithmic approach.
You can change your code to this:
data = {}
currentKey = ""
foreach (line in inputData) {
key, value = split(line)
if (currentKey != key) {
data[key] = [] // like data.put(key,new ArrayList<String>()) in java
}
data[key].add(value) // like data.get(key).add(value) in java
currentKey = key
}
Here is a solution. First, create a map. For each entry in your data file, find the key and value. Check if the key is in the map. If it isn't, add a new list to the map containing the new value for that key. If the key is already in the map, just add the new value to the list.
def hash = [:]
new File("test.data").eachLine { String line ->
def (key,value) = line.split(/\|/)
hash.get(key, []) << value
}
println hash
It prints out the following map:
[key1:[value1, value2, value3], key2:[value4, value5]]
No need to keep track of currentKey.
Edit: This is written in Groovy, but should be implemented quite similarly in other languages. hash.get() returns the value for the key, or the provided default value (in the above snippet, an empty list), while the left-shift (<<) operator adds something to the list.

does ruby have an elegant way to say array2 = some_lookup_method(array1)

I have an array short_code[] that contains an array of short product identifiers such as ["11111", "2222", "33333"]
I want to create a copy of the array that contains the corresponding 'long code' data:
long_code[i] = my_lookup_long_code(short_code[i])
While simple iteration is easy, I'm wondering, as a relative ruby newbie, what is the 'ruby way' to create an array which is a simply method() applied on every element in the original array?
You can use the map command, which will return a new array with the results of your code block:
long_code = short_code.map{ |code| my_lookup_long_code(code) }

Resources