I have included given code
#students = "All #{section.count}#{section.values}"
output: "All 9['A','B','C','D','E','F','G','H','I']"
But I want show output to be All 9['A','B','C',...]
Please guide me how to solve this. Thanks in advance.
You can print first 3 elements of Array and then manipulate the String to include ellipsis. Here:
section.values
# => ["A", "B", "C", "D", "E", "F", "G", "H", "I"]
puts "#{section.values[0..2]}".sub("]",", ...]")
# ["A", "B", "C", ...]
You can use #take method too. Example:
a = [1,2,3,4,5]
a.take(2) # will give as result [1,2]
Hope it will help.
You can do this
#students = "All #{section.count}#{(section.count > 3) ? (section.values[0..2] << '...') : section.values}"
Hope that helps!
first get all records and store it on #student.
and use first() method
#student.first(count)
Related
I have a hash and an array. I want to check whether an array element is in the hash as a key, and if not, delete the key from the hash.
RegionScoreHash={"A"=>1, "B"=>0, "C"=>0, "D"=>1, "E"=>0, "F"=>0, "G"=>0}
RegionsArray=["B", "C", "D", "E", "F"]
Result Required: Hash with elements present in array (A and G regions removed)
ResultHash={"B"=>0, "C"=>0, "D"=>1, "E"=>0, "F"=>0}
Use Array's delete_if method to modify the hash in place.
RegionScoreHash.delete_if { |k| !RegionsArray.include?(k) }
or use something like select if you want a new result.
result = RegionScoreHash.select { |k| RegionsArray.include?(k) }
Deleting is inefficient.
ResultHash = RegionsArray.inject({}){|h, k| h[k] = RegionScoreHash[k]; h}
Try this
RegionScoreHash={"A"=>1, "B"=>0, "C"=>0, "D"=>1, "E"=>0, "F"=>0, "G"=>0}
RegionsArray=["B", "C", "D", "E", "F"]
RegionScoreHash.delete_if {|a| !RegionsArray.include?(a)}
As advice the ruby way should be region_score_hash instead RegionScoreHash.
Since you've tagged ruby-on-rails, let's assume you have ActiveSupport's extensions to Enumerable, which allows use of exclude?
Combine it with Hash's delete_if method
RegionScoreHash.delete_if { |k, _v| RegionsArray.exclude?(k) }
and you should get back a hash with only keys that are present in RegionsArray.
For an array like this:
a = [{a:'a',b:'3'},{a:'b',b:'2'},{a:'c',b:'1'}]
I would like to return an array containing values for :a keys, so:
['a', 'b', 'c']
That can be done using:
a.map{|x|x[:a]}
I wonder if there is a native method in Rails or Ruby to do it like this?
a.something :a
You can do it yourself:
class Array
def get_values(key)
self.map{|x| x[key]}
end
end
Then you can do this:
a.get_values :a
#=> ["a", "b", "c"]
More than you need in this case, but from How to merge array of hashes to get hash of arrays of values you can get them all at once:
merged = a.inject{ |h1,h2| h1.merge(h2){ |_,v1,v2| [*v1,*v2] } }
p merged[:a] #=> ["a", "b", "c"]
p merged[:b] #=> ["3", "2", "1"]
Also, if you use something like Struct or OpenStruct for your values instead of hashes—or any object that allows you to get the "a" values as a method that does not require parameters—you can use the Symbol#to_proc convenience for your map:
AB = Struct.new(:a,:b)
all = [ AB.new('a','3'), AB.new('b','2'), AB.new('c','1') ]
#=> [#<AB a="a", b="3">, #<AB a="b", b="2">, #<AB a="c", b="1">]
all.map(&:a) #=> ["a", "b", "c"]
all.map(&:b) #=> ["3", "2", "1"]
This question already has answers here:
Why are exclamation marks used in Ruby methods?
(12 answers)
Closed 8 years ago.
From Ruby's official documentation:
sort → new_ary sort { |a, b| block } → new_ary Returns a new array
created by sorting self.
Comparisons for the sort will be done using the <=> operator or using
an optional code block.
The block must implement a comparison between a and b, and return -1,
when a follows b, 0 when a and b are equivalent, or +1 if b follows a.
See also Enumerable#sort_by.
a = [ "d", "a", "e", "c", "b" ]
a.sort #=> ["a", "b", "c", "d", "e"]
a.sort { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
sort! → ary click to toggle source sort! { |a, b| block } → ary Sorts
self in place.
Comparisons for the sort will be done using the <=> operator or using
an optional code block.
The block must implement a comparison between a and b, and return -1,
when a follows b, 0 when a and b are equivalent, or +1 if b follows a.
See also Enumerable#sort_by.
a = [ "d", "a", "e", "c", "b" ]
a.sort! #=> ["a", "b", "c", "d", "e"]
a.sort! { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
The result seems the same, so what's the difference?
sort will not modify the original array whereas sort! will
('!' is the bang method in ruby, it will replace the existing value)
For example:
a = [4,3,2,5,1]
a.sort # => [1,2,3,4,5]
a is still [4,3,2,5,1]
where as
a = [4,3,2,5,1]
a.sort! # => [1,2,3,4,5]
a is now [1,2,3,4,5]
In rails ! used to apply changes and update its calling object means
a.sort will only return sorted array but a.sort! will return sorted array and also save new sort result in a variable.
'!' is the bang method in ruby, it will replace the existing value
ex: .sort is a normal sorting method in ruby
.sort! its a bang method in ruby its override the existing value.
One of my objects ('item') has an ID ('letter_id') in the format of "a", "b", ..., "aa", "ab", etc. To generate it I am using ruby's String#succ in an instance method like this:
def set_letter_id
last = parent.items.all(:order => "letter_id ASC").last
if last.nil?
self.letter_id = 'a'
else
self.letter_id = last.letter_id.succ
end
end
Now this works great until the 28th letter. The 27th will properly generate "aa", but then the value of last will always return the item with the letter_id of 'z' because the ordering of the returned items doesn't follow the same rules as String#succ.
I found this out from a comment over here - but now I'm struggling to find a nice solution around this issue. The problem is basically this:
"aa".succ #=> "ab" - great, that's what I want.
"z"<=>"aa" #=> 1 - not so great, "z" should actually be less than "aa"
Obviously this isn't necessarily a bug, but it makes sorting and ordering a list of letter_ids in this format quite difficult. Has anyone encountered this and found a workaround, or any suggestions that I might try? Thanks!
There was a solution in answers at link you've posted - you have to write own <=> in way to sort_by{|i|[i.length,i]}
irb> %w{a b c z aa ab zz aaa}.shuffle.sort_by { |i| [i.length,i] }
=> ["a", "b", "c", "z", "aa", "ab", "zz", "aaa"]
You can override the <=> method for your Item model to compare first by ID length, then by alphanumeric.
Something like this:
class Item < ActiveRecord::Base
# stuff
def <=>(other)
len_comp = self.letter_id.length <=> other.letter_id.length
return len_comp if len_comp != 0
self.letter_id <=> other.letter_id
end
end
That way you first compare for shorter ID length (i.e., "z" before "aa"), then lexicographically.
This sort of issue is exactly why some people discourage the use of String#succ. It clashes with Range, Object#to_a, and others.
Anyway, you probably know this, but things like this might help...
>> t
=> ["x", "y", "z", "aa", "ab", "ac", "ad", "ae", "af", "ag"]
>> t.shuffle.sort_by { |e| "%3s" % [e] }
=> ["x", "y", "z", "aa", "ab", "ac", "ad", "ae", "af", "ag"]
You could even renormalize this way and dispense with sort_by.
I'm hopelessly trying to write a method to manipulate an array in ruby. I'm trying to generate all in-order permutations of an array where each item is in turn replaced by an outside item. An example...
Given input:
arr = ["a", "b", "c"]
Desired output:
newArr = [ ["a", "b", "c"], ["a", "b", "*"], ["a", "*", "c"], ["a", "*", "*"], ["*", "b", "c"], ["*", "b", "*"], ["*", "*", "c"], ["*", "*", "*"] ]
Any help would be greatly appreciated. Thank you!
I don't understand your example order, either, but ignoring that, here's a solution in one line:
(0...(2**a.size)).map {|x| (0...a.size).map {|y| x & 2**y == 0 ? a[y] : val}}
I'm not sure permutation is the right word. If you count in binary, then you are replacing the things if there is a one. Here's that in Ruby:
def mike(arr, sub)
format = sprintf("%%0%db", arr.length)
m = Array.new
0.upto(2**arr.length-1) { |i|
bits = sprintf(format, i).split('')
a = Array.new
0.upto(arr.length-1) { |j|
if bits[j] == '0' then
a << arr[j]
else
a << sub
end
}
m[i] = a
}
return m
end
arr = ["a", "b", "c"]
p mike(arr, '*')
Is that if-then-else better with a ternary operator?
a <<= bits[j] == '0' ? arr[j] : sub
There must be a cleverer (or, at least more Rubyesque) way to do this, but it seems to produce the desired output.
ETA: Oops! My second and third items don't agree with yours. I guess I don't know what order you mean.
Similar to oylenshpeegui's method:
def toggle(arr, sub)
format = "%0#{arr.length}b"
(0...2**(arr.length)).to_a.map do |i|
sprintf(format,i).split('').zip(arr).map { |x| x[0] == "0" ? x[1] : sub }
end
end
The split/zip combo matches each digit of the binary expansion of the index with the element it is selecting. The map at the end uses the digit to decide if it should return the array element or the substitution.