I am trying to remove white space of array elements, but at the same time I want this to be inline replacement. Is something like this can be done..
lines[3..lines.length-4].map!(&:strip).delete_if { |table_name| table_name == "" }
It does not work because lines[3..lines.length-4] returns a new array, not a partial "reference" to the old one (so your map! is then just modifying in-place this new array).
An idea:
(3..lines.length-4).each { |idx| lines[idx].strip! }
When you call map! on lines[3..lines.length-4] this method is called not on your original array but on a new one, that contains slice of the original lines array. If what you need is to replace part of your lines array with its stripped and filtered elements you can do it like that:
lines[3..lines.length-4] = lines[3..lines.length-4].map(&:strip).reject { |tn| tn == "" }
Here you explicitly override slice of lines array after striping and filtering elements it contains.
Related
With a normal array, I can use the arrayname.find_index('whatimlookingfor') to get the position within the array.
I can't figure out how to do this when the elements of the array are Struct's.
Scenario: I have a struct that consists of an ID and the Filename. In one function I need to find within that array the ID of a different file than the one I'm currently processing. I know the other filename, so what I was hoping that I could do something like:
arrayname.filename.find_index(parsedfilename)
But this obviously fails. Without iterating through the entire array is there a way to quickly reference the index of where the match happens? Or am I out of luck because the array is a collection of structs?
index (same as find_index) takes a block in which you can code up any true/false logic for your finder. To find the index of the first item whose filename does not match parsedfilename...
found_index = items.index { |item| item.filename != parsedfilename }
Many methods which work with Arrays and Enumerables also take blocks.
I've been successfully converting an array of objects into an array of hashes. But I also want to modify the objects slightly as well, before getting the combined hash.
This is what I do to convert array of objects into a combined hash:
prev_vars.map(&:to_h).reduce({}, :merge)
{ "b"=>#<Money fractional:400 currency:GBP> }
But what I want to have instead, which required to additionally call to_i is:
{ "b"=> 4 }
I got this working using this line, but I am looking for a more elegant solution:
prev_vars.map(&:to_h).reduce({}) { |combined, v| combined.merge({v.keys[0] => v.values[0].to_i}) }
How large is prev_vars? map(&:to_h) could require a fair amount of memory overhead, because it instantiates an entirely new array. Instead, I'd recommend switching the order: first #reduce, then #to_h:
prev_vars.reduce({}) do |combined, var|
combined.merge! var.to_h.transform_values!(&:to_i)
end
Note the use of #merge! rather than #merge so that a new hash is not created for combined for each iteration of the loop.
I'm trying to be really efficient with # of lines of code so I want to combine the following two lines of code:
my_hash["X"] = value
my_hash
If I take out the second line, then my function returns the wrong thing because it will only return the one element of the hash. Is there any way to add the element to the hash that will return the whole hash? Thanks in advance!
Do as below using merge! :
my_hash.merge!("X" => value)
tap will yield the object to a block, and then return it:
my_hash.tap { |h| h['X'] = value }
Be aware that reducing lines of code for the sake of reducing lines of code only reduces readability and clarity of purpose, it rarely improves code quality.
my_hash.merge!( { 'X' => value } )
I am currently trying to compare every element of an array with the others (in Ruby). Those elements are objects of a class. I need to find similarities between them. My idea was to loop through the original array and in this loop creating a new array containing the other elements (not the one of the outer loop) and then loop through this second array and compare every item with the one in the outer each loop.
Here is some pseudocode:
originalArray.each{
|origElement|
tempArray = createNewArray from original array without origElement
tempArray.each{
|differentElement|
Compare origElement with differentElement
}
}
How can I create that tempArray?
I think you should use Array#permutation for this
original_array.permutation(2) { |elements| Compare elements[0] with elements[1] }
First, I want to say bjhaid's answer is beautiful and for your specific instance, it is the one that should be used.
However, I wanted to provide a more general answer that answers the direct question you asked: "How can I create that tempArray?"
If you wanted to delete all values that are equal to the element in the original array, you could simply do:
tempArray = originalArray - [origElement]
However, if you only want to delete that element, you could do:
originalArray.each_with_index {
|origElement, index|
tempArray = originalArray.dup
tempArray.delete_at(index)
tempArray.each{
|differentElement|
Compare origElement with differentElement
}
}
Also, a note on styling. You probably want to use underscores instead of CamelCase for all methods/variables. In the Ruby community, CamelCase is typically reserved for class / module names. You also probably want to keep the "piped-in" variables (called block arguments) on the same line as the beginning of the block. It is certainly not a requirement, but it is an almost universal convention in the Ruby community.
This code snippet would be much more familiar and readable to your typical Ruby dev:
original_array.each_with_index do |orig_element, index|
temp_array = original_array.dup
temp_array.delete_at(index)
temp_array.each do |different_element|
Compare orig_element with different_element
end
end
myitem.inject({}) {|a,b| a[b.one] = b.two; a}
Where:
myitem is a class which holds an array or pair objects (pair objects have two fields in them one and two)
I am not sure what the above code is supposed to do?
Starting with an empty map, set its value for the b.one key to b.two.
In other words, for every item in the "myitem" collection, create a map entry. The key will be an item's "one" value. That map entry's value will be the item's "two" value.
The block given to "inject" receives two parameters. The first is the "accumulator". It's initial value in this case is the empty map passed to "inject". The second parameter is the current item in the collection. In this case, each item in the collection.
The block must return whatever will be used as the next accumulator value, in this case, the map. We want to keep using the same map, so when we're done, the "inject" method will return the map with all the key/value pairs.
Without saving the results of the inject it's a bit worthless.
It's a pedantic way of writing
h = {}
myitem.each { |b| h[b.one] = b.two }
or to be closer to your original code
a = {}
mytem.each { |b| a[b.one] = b.two }
(I personnaly hate this pattern (and people who use it) as it needs the ; a at the end, losing all the functional aspect of inject. (Using a side-effect function inside a 'functional pattern', and then realizing that the later function (a[..]) doesn't return the expecting object is just wrong, IMO).
Inject is normal use to 'fold' a list into a result like
[1,2,3].inject(0) { |sum, x| sum+x }
=> 6 # (0+1+2+3)
here sum is the result of the last call to the block, x is each value on the list and 0 is the initial value of sum.
[2,3].inject(10) { |p,x| p*x }
=> 60 # 10*2*3
etc ...
Hash[my_item.map {|object| [object.one, object.two]}]
is another way to do it.